如何在 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
再说一次,您可能不需要编码为字符串。
我有一个 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
再说一次,您可能不需要编码为字符串。