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

huangapple go评论119阅读模式
英文:

How to decode hex to ASN.1 in golang

问题

我有一个以ASN.1 DER格式从HSM返回给我的ECDSA公钥。我需要创建一个与比特币兼容的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...的输出?

谢谢。

英文:

I have an ECDSA public key that that is returned to me from an HSM in ASN.1 DER format. I need to create a bitcoin compatible key 33 byte. When I print out key in hex.EncodeToString(pubkey) I get the following output:
3056301006072a8648ce3d020106052b8104000a034200049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec

I use an online decoder here: https://holtstrom.com/michael/tools/asn1decoder.php

And it outputs:
0x049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec

I can then take that and hex.DecodeString(str) which gives me the necessary format to input this into addrPubKey, err := btcutil.NewAddressPubKey(bs, &chaincfg.TestNet3Params).

How do I decode this in golang to get the 0x049... output?

Thanks

答案1

得分: 0

我们首先需要使用标准库中的encoding/asn1包
你只需要给go正确的结构体进行解码。从你的链接中我们可以看到有一个包含另一个SEQUENCESEQUENCE,其中包含两个OBJECTIDENTIFIER和一个BITSTRING。在go中,这将是:

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

type PubKey struct {
	Id Ids
	Bs asn1.BitString
}

现在我们只需要将数据解组到这个结构中:

	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

再次说明,你可能不需要将其编码为字符串。

英文:

The first thing we need is to use the encoding/asn1 package from the standard library.
You only have to give go the right struct to decode into. From your link we can see that we have a SEQUENCE that contains another SEQUENCE with two OBJECTIDENTIFIER and a BITSTRING. In go this will be:

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

type PubKey struct {
	Id Ids
	Bs asn1.BitString
}

Now we only have to UnMarshall the data to this structure:

	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))

Note that you don't have to encode the string to hex and back again, since Unmarshall accepts a byte array

This will print the expected result:

049bb8e80670371f45508b5f8f59946a7c4dea4b3a23a036cf24c1f40993f4a1daad1716de8bd664ecb4596648d722a4685293de208c1d2da9361b9cba74c3d1ec

Once again you probably don't need to encode to string.

huangapple
  • 本文由 发表于 2021年9月29日 12:00:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/69370234.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定