gomarshallingunmarshallingasn.1

How to Go asn1 marshal/unmarshal and omit fields?


type bearer struct {
    CreatedAt time.Time     `asn1:"generalized"`
    ExpiresAt time.Time     `asn1:"generalized"`
    Nonce     string
    Signature []byte        `asn1:"-"`
    TTL       time.Duration `asn1:"-"`
    Frequency int           `asn1:"-"`
}

c := &bearer{
  CreatedAt: time.Now()
  ExpiresAt: time.Now().Add(1*time.Minute())
  Nonce: "123456789abcdefghijklmnop"
  Frequency: 1
}

b, err := asn1.Marshal(*c)
os.WriteFile("b64.txt", b, 0777)

Will successfully marshal the struct, however, when checking that struct with Bash base64 -d b64.txt > b64.txt.der I can still see that asn1:"-" fields were actually marshalled and written to file, and field which didn't have a value got Error: Object has zero length.. Why asn1:"-" doesnt work as it does for json?


Solution

  • Why asn1:"-" doesnt work as it does for json?

    Because the encoding/json package is implemented to support the - option, while encoding/asn1 isn't. As to why, this is not the place. Accept that primary goal of encoding/asn1 is to support reading and writing X.509 certificates, it doesn't mean to be a "swiss army knife" of ASN1 implementation.

    If you want to exclude certain fields, create struct types that exclude those fields. To avoid repetition, you may embed these "stripped" structs in your own that includes the additional fields, e.g.:

    type bearerAsn1 struct {
        CreatedAt time.Time `asn1:"generalized"`
        ExpiresAt time.Time `asn1:"generalized"`
        Nonce     string
    }
    
    type bearer struct {
        bearerAsn1
        Signature []byte
        TTL       time.Duration
        Frequency int
    }
    

    Only marshal / unmarshal bearer.bearerAsn1, so other fields of bearer will be naturally excluded.