Home > Software design >  How to decode hex to ASN.1 in golang
How to decode hex to ASN.1 in golang

Time:09-30

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

CodePudding user response:

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.

  • Related