如何在 golang 中将十六进制解码为 ASN.1

How to decode hex to ASN.1 in golang

我有一个 ECDSA public 密钥,它以 ASN.1 DER 格式从 HSM 返回给我。我需要创建一个 33 字节的比特币兼容密钥。当我打印 hex.EncodeToString(pubkey) 中的键时,我得到以下输出: 3056301006072a8648ce3d020106052b8104000a034200049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec

我这里使用在线解码器:https://holtstrom.com/michael/tools/asn1decoder.php

它输出: 0x049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec

然后我可以接受那个 hex.DecodeString(str) 这给了我必要的格式来输入这个到 addrPubKey, err := btcutil.NewAddressPubKey(bs, &chaincfg.TestNet3Params).

我如何在 golang 中对此进行解码以获得 0x049... 输出?

谢谢

我们首先需要使用标准库中的encoding/asn1 package。 你只需要给出正确的结构来解码。从您的 link 我们可以看到我们有一个 SEQUENCE,其中包含另一个 SEQUENCE 以及两个 OBJECTIDENTIFIER 和一个 BITSTRING。这将是:

type Ids struct {
    OBi1 asn1.ObjectIdentifier
    OBi2 asn1.ObjectIdentifier
}

type PubKey struct {
    Id Ids
    Bs asn1.BitString
}

现在我们只需要UnMarshall数据到这个结构:

    str := `3056301006072a8648ce3d020106052b8104000a034200049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec`

    bstring, err := hex.DecodeString(str)
    if (err != nil) {
        panic(err)
    }

    var decode PubKey
    _, err = asn1.Unmarshal(bstring, &decode)
    if (err != nil) {
        panic(err)
    }
    fmt.Println(hex.EncodeToString(decode.Bs.Bytes))

请注意,您不必将字符串编码为十六进制并再次编码,因为 Unmarshall 接受字节数组

这将打印预期结果:

049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec

再说一次,您可能不需要编码为字符串。