goasn.1

Retrieve value stored against an OID from inside SAN in golang


I can access get subjectAltName using following code:

    for _, ext := range certificate.Extensions {
        if ext.Id.Equal(subjectAltNameOID) {
            var extensionData asn1.RawValue
            _, err := asn1.Unmarshal(ext.Value, &extensionData)
            if err != nil {
                log.Fatal(err)
            }

            // get value for OID "2.23.33.5.1.6"
            
            return
        }
    }

var subjectAltNameOID = []int{2, 5, 29, 17}

but how can I now retrieve the data from extensionData?


        Extension SEQUENCE (2 elem)
          extnID OBJECT IDENTIFIER 2.5.29.17 subjectAltName (X.509 extension)
          extnValue OCTET STRING (79 byte) 304D06066781050501010C09585886868768686806F7765…
            SEQUENCE (8 elem)
              OBJECT IDENTIFIER 2.23.33.5.1.1
              UTF8String hello
              OBJECT IDENTIFIER 2.23.33.5.1.4
              UTF8String power
              OBJECT IDENTIFIER 2.23.33.5.1.5
              UTF8String Unknown
              OBJECT IDENTIFIER 2.23.33.5.1.6 
              UTF8String 1234

Solution

  • The Golang standard library contains an unexported function, parseSANExtension, that parses an SAN extension:

    func parseSANExtension(der cryptobyte.String) (dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL, err error)
    

    It also contains a function, marshalSANs, that marshals an SAN extension:

    // marshalSANs marshals a list of addresses into a the contents of an X.509
    // SubjectAlternativeName extension.
    func marshalSANs(dnsNames, emailAddresses []string, ipAddresses []net.IP, uris []*url.URL) (derBytes []byte, err error)
    

    You can copy the source code from the standard library. And then call parseSANExtension(ext.Value) to get the values stored in the extension.

    Try this demo: https://go.dev/play/p/ZkaVBIVp3GB.