func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, os.Error) { asn1Data := keyData.PublicKey.RightAlign() switch algo { case RSA: p := new(rsaPublicKey) _, err := asn1.Unmarshal(asn1Data, p) if err != nil { return nil, err } if !rawValueIsInteger(&p.N) { return nil, asn1.StructuralError{"tags don't match"} } pub := &rsa.PublicKey{ E: p.E, N: new(big.Int).SetBytes(p.N.Bytes), } return pub, nil case DSA: p := new(asn1.RawValue) _, err := asn1.Unmarshal(asn1Data, p) if err != nil { return nil, err } if !rawValueIsInteger(p) { return nil, asn1.StructuralError{"tags don't match"} } paramsData := keyData.Algorithm.Parameters.FullBytes params := new(dsaAlgorithmParameters) _, err = asn1.Unmarshal(paramsData, params) if err != nil { return nil, err } if !rawValueIsInteger(¶ms.P) || !rawValueIsInteger(¶ms.Q) || !rawValueIsInteger(¶ms.G) { return nil, asn1.StructuralError{"tags don't match"} } pub := &dsa.PublicKey{ Parameters: dsa.Parameters{ P: new(big.Int).SetBytes(params.P.Bytes), Q: new(big.Int).SetBytes(params.Q.Bytes), G: new(big.Int).SetBytes(params.G.Bytes), }, Y: new(big.Int).SetBytes(p.Bytes), } return pub, nil default: return nil, nil } panic("unreachable") }
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) { var priv pkcs1PrivateKey rest, err := asn1.Unmarshal(der, &priv) if len(rest) > 0 { err = asn1.SyntaxError{"trailing data"} return } if err != nil { return } if !rawValueIsInteger(&priv.N) || !rawValueIsInteger(&priv.D) || !rawValueIsInteger(&priv.P) || !rawValueIsInteger(&priv.Q) { err = asn1.StructuralError{"tags don't match"} return } key = &rsa.PrivateKey{ PublicKey: rsa.PublicKey{ E: priv.E, N: new(big.Int).SetBytes(priv.N.Bytes), }, D: new(big.Int).SetBytes(priv.D.Bytes), P: new(big.Int).SetBytes(priv.P.Bytes), Q: new(big.Int).SetBytes(priv.Q.Bytes), } err = key.Validate() if err != nil { return nil, err } return }
// ParseDER parses a DER encoded CRL from the given bytes. func ParseDER(derBytes []byte) (certList *CertificateList, err os.Error) { certList = new(CertificateList) _, err = asn1.Unmarshal(derBytes, certList) if err != nil { certList = nil } return }
// ParseDERCRL parses a DER encoded CRL from the given bytes. func ParseDERCRL(derBytes []byte) (certList *pkix.CertificateList, err error) { certList = new(pkix.CertificateList) _, err = asn1.Unmarshal(derBytes, certList) if err != nil { certList = nil } return }
func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{}, os.Error) { asn1Data := keyData.PublicKey.RightAlign() switch algo { case RSA: p := new(rsaPublicKey) _, err := asn1.Unmarshal(asn1Data, p) if err != nil { return nil, err } pub := &rsa.PublicKey{ E: p.E, N: p.N, } return pub, nil case DSA: var p *big.Int _, err := asn1.Unmarshal(asn1Data, &p) if err != nil { return nil, err } paramsData := keyData.Algorithm.Parameters.FullBytes params := new(dsaAlgorithmParameters) _, err = asn1.Unmarshal(paramsData, params) if err != nil { return nil, err } if p.Sign() <= 0 || params.P.Sign() <= 0 || params.Q.Sign() <= 0 || params.G.Sign() <= 0 { return nil, os.NewError("zero or negative DSA parameter") } pub := &dsa.PublicKey{ Parameters: dsa.Parameters{ P: params.P, Q: params.Q, G: params.G, }, Y: p, } return pub, nil default: return nil, nil } panic("unreachable") }
// ParsePKIXPublicKey parses a DER encoded public key. These values are // typically found in PEM blocks with "BEGIN PUBLIC KEY". func ParsePKIXPublicKey(derBytes []byte) (pub interface{}, err os.Error) { var pki publicKeyInfo if _, err = asn1.Unmarshal(derBytes, &pki); err != nil { return } algo := getPublicKeyAlgorithmFromOID(pki.Algorithm.Algorithm) if algo == UnknownPublicKeyAlgorithm { return nil, os.NewError("ParsePKIXPublicKey: unknown public key algorithm") } return parsePublicKey(algo, &pki) }
// ParseCertificate parses a single certificate from the given ASN.1 DER data. func ParseCertificate(asn1Data []byte) (*Certificate, os.Error) { var cert certificate rest, err := asn1.Unmarshal(asn1Data, &cert) if err != nil { return nil, err } if len(rest) > 0 { return nil, asn1.SyntaxError{"trailing data"} } return parseCertificate(&cert) }
func decode(data []byte) (interface{}, os.Error) { m := Message{} _, err := asn1.Unmarshal(data, &m) if err != nil { fmt.Errorf("%#v", data) return nil, err } choice := m.Data.FullBytes[0] switch choice { case 0xa0, 0xa1, 0xa2: // Response pdu := new(PDU) // hack ANY -> IMPLICIT SEQUENCE m.Data.FullBytes[0] = 0x30 _, err = asn1.Unmarshal(m.Data.FullBytes, pdu) if err != nil { return nil, fmt.Errorf("%#v, %#v, %s", m.Data.FullBytes, pdu, err) } return pdu, nil } return nil, fmt.Errorf("Unknown CHOICE: %x", choice) }
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err os.Error) { var priv pkcs1PrivateKey rest, err := asn1.Unmarshal(der, &priv) if len(rest) > 0 { err = asn1.SyntaxError{"trailing data"} return } if err != nil { return } if priv.Version > 1 { return nil, os.ErrorString("x509: unsupported private key version") } if !rawValueIsInteger(&priv.N) || !rawValueIsInteger(&priv.D) || !rawValueIsInteger(&priv.P) || !rawValueIsInteger(&priv.Q) { err = asn1.StructuralError{"tags don't match"} return } key = new(rsa.PrivateKey) key.PublicKey = rsa.PublicKey{ E: priv.E, N: new(big.Int).SetBytes(priv.N.Bytes), } key.D = new(big.Int).SetBytes(priv.D.Bytes) key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) key.Primes[0] = new(big.Int).SetBytes(priv.P.Bytes) key.Primes[1] = new(big.Int).SetBytes(priv.Q.Bytes) for i, a := range priv.AdditionalPrimes { if !rawValueIsInteger(&a.Prime) { return nil, asn1.StructuralError{"tags don't match"} } key.Primes[i+2] = new(big.Int).SetBytes(a.Prime.Bytes) // We ignore the other two values because rsa will calculate // them as needed. } err = key.Validate() if err != nil { return nil, err } key.Precompute() return }
// ParsePKCS1PrivateKey returns an RSA private key from its ASN.1 PKCS#1 DER encoded form. func ParsePKCS1PrivateKey(der []byte) (key *rsa.PrivateKey, err error) { var priv pkcs1PrivateKey rest, err := asn1.Unmarshal(der, &priv) if len(rest) > 0 { err = asn1.SyntaxError{"trailing data"} return } if err != nil { return } if priv.Version > 1 { return nil, errors.New("x509: unsupported private key version") } if priv.N.Sign() <= 0 || priv.D.Sign() <= 0 || priv.P.Sign() <= 0 || priv.Q.Sign() <= 0 { return nil, errors.New("private key contains zero or negative value") } key = new(rsa.PrivateKey) key.PublicKey = rsa.PublicKey{ E: priv.E, N: priv.N, } key.D = priv.D key.Primes = make([]*big.Int, 2+len(priv.AdditionalPrimes)) key.Primes[0] = priv.P key.Primes[1] = priv.Q for i, a := range priv.AdditionalPrimes { if a.Prime.Sign() <= 0 { return nil, errors.New("private key contains zero or negative prime") } key.Primes[i+2] = a.Prime // We ignore the other two values because rsa will calculate // them as needed. } err = key.Validate() if err != nil { return nil, err } key.Precompute() return }
// CheckSignature verifies that signature is a valid signature over signed from // c's public key. func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err os.Error) { var hashType crypto.Hash switch algo { case SHA1WithRSA, DSAWithSHA1: hashType = crypto.SHA1 case SHA256WithRSA, DSAWithSHA256: hashType = crypto.SHA256 case SHA384WithRSA: hashType = crypto.SHA384 case SHA512WithRSA: hashType = crypto.SHA512 default: return UnsupportedAlgorithmError{} } h := hashType.New() if h == nil { return UnsupportedAlgorithmError{} } h.Write(signed) digest := h.Sum() switch pub := c.PublicKey.(type) { case *rsa.PublicKey: return rsa.VerifyPKCS1v15(pub, hashType, digest, signature) case *dsa.PublicKey: dsaSig := new(dsaSignature) if _, err := asn1.Unmarshal(signature, dsaSig); err != nil { return err } if !rawValueIsInteger(&dsaSig.R) || !rawValueIsInteger(&dsaSig.S) { return asn1.StructuralError{"tags don't match"} } r := new(big.Int).SetBytes(dsaSig.R.Bytes) s := new(big.Int).SetBytes(dsaSig.S.Bytes) if !dsa.Verify(pub, digest, r, s) { return os.ErrorString("DSA verification failure") } return } return UnsupportedAlgorithmError{} }
// CheckSignature verifies that signature is a valid signature over signed from // c's public key. func (c *Certificate) CheckSignature(algo SignatureAlgorithm, signed, signature []byte) (err os.Error) { var hashType crypto.Hash switch algo { case SHA1WithRSA, DSAWithSHA1: hashType = crypto.SHA1 case SHA256WithRSA, DSAWithSHA256: hashType = crypto.SHA256 case SHA384WithRSA: hashType = crypto.SHA384 case SHA512WithRSA: hashType = crypto.SHA512 default: return UnsupportedAlgorithmError{} } h := hashType.New() if h == nil { return UnsupportedAlgorithmError{} } h.Write(signed) digest := h.Sum() switch pub := c.PublicKey.(type) { case *rsa.PublicKey: return rsa.VerifyPKCS1v15(pub, hashType, digest, signature) case *dsa.PublicKey: dsaSig := new(dsaSignature) if _, err := asn1.Unmarshal(signature, dsaSig); err != nil { return err } if dsaSig.R.Sign() <= 0 || dsaSig.S.Sign() <= 0 { return os.NewError("DSA signature contained zero or negative values") } if !dsa.Verify(pub, digest, dsaSig.R, dsaSig.S) { return os.NewError("DSA verification failure") } return } return UnsupportedAlgorithmError{} }
func parsePublicKey(algo PublicKeyAlgorithm, asn1Data []byte) (interface{}, os.Error) { switch algo { case RSA: p := new(rsaPublicKey) _, err := asn1.Unmarshal(asn1Data, p) if err != nil { return nil, err } if !rawValueIsInteger(&p.N) { return nil, asn1.StructuralError{"tags don't match"} } pub := &rsa.PublicKey{ E: p.E, N: new(big.Int).SetBytes(p.N.Bytes), } return pub, nil default: return nil, nil } panic("unreachable") }
// ParseCertificates parses one or more certificates from the given ASN.1 DER // data. The certificates must be concatenated with no intermediate padding. func ParseCertificates(asn1Data []byte) ([]*Certificate, os.Error) { var v []*certificate for len(asn1Data) > 0 { cert := new(certificate) var err os.Error asn1Data, err = asn1.Unmarshal(asn1Data, cert) if err != nil { return nil, err } v = append(v, cert) } ret := make([]*Certificate, len(v)) for i, ci := range v { cert, err := parseCertificate(ci) if err != nil { return nil, err } ret[i] = cert } return ret, nil }
// ParseCertificates parses one or more certificates from the given ASN.1 DER // data. The certificates must be concatenated with no intermediate padding. func ParseCertificates(asn1Data []byte) ([]*Certificate, os.Error) { v := new(vector.Vector) for len(asn1Data) > 0 { cert := new(certificate) var err os.Error asn1Data, err = asn1.Unmarshal(asn1Data, cert) if err != nil { return nil, err } v.Push(cert) } ret := make([]*Certificate, v.Len()) for i := 0; i < v.Len(); i++ { cert, err := parseCertificate(v.At(i).(*certificate)) if err != nil { return nil, err } ret[i] = cert } return ret, nil }
// ParseResponse parses an OCSP response in DER form. It only supports // responses for a single certificate and only those using RSA signatures. // Non-RSA responses will result in an x509.UnsupportedAlgorithmError. // Signature errors or parse failures will result in a ParseError. func ParseResponse(bytes []byte) (*Response, error) { var resp responseASN1 rest, err := asn1.Unmarshal(bytes, &resp) if err != nil { return nil, err } if len(rest) > 0 { return nil, ParseError("trailing data in OCSP response") } ret := new(Response) if resp.Status != ocspSuccess { ret.Status = ServerFailed return ret, nil } if !resp.Response.ResponseType.Equal(idPKIXOCSPBasic) { return nil, ParseError("bad OCSP response type") } var basicResp basicResponse rest, err = asn1.Unmarshal(resp.Response.Response, &basicResp) if err != nil { return nil, err } if len(basicResp.Certificates) != 1 { return nil, ParseError("OCSP response contains bad number of certificates") } if len(basicResp.TBSResponseData.Responses) != 1 { return nil, ParseError("OCSP response contains bad number of responses") } ret.Certificate, err = x509.ParseCertificate(basicResp.Certificates[0].FullBytes) if err != nil { return nil, err } if ret.Certificate.PublicKeyAlgorithm != x509.RSA || !basicResp.SignatureAlgorithm.Algorithm.Equal(idSHA1WithRSA) { return nil, x509.UnsupportedAlgorithmError{} } hashType := crypto.SHA1 h := hashType.New() pub := ret.Certificate.PublicKey.(*rsa.PublicKey) h.Write(basicResp.TBSResponseData.Raw) digest := h.Sum() signature := basicResp.Signature.RightAlign() if rsa.VerifyPKCS1v15(pub, hashType, digest, signature) != nil { return nil, ParseError("bad OCSP signature") } r := basicResp.TBSResponseData.Responses[0] ret.SerialNumber = r.CertID.SerialNumber.Bytes switch { case bool(r.Good): ret.Status = Good case bool(r.Unknown): ret.Status = Unknown default: ret.Status = Revoked ret.RevokedAt = r.Revoked.RevocationTime ret.RevocationReason = r.Revoked.Reason } ret.ProducedAt = basicResp.TBSResponseData.ProducedAt ret.ThisUpdate = r.ThisUpdate ret.NextUpdate = r.NextUpdate return ret, nil }
func parseCertificate(in *certificate) (*Certificate, os.Error) { out := new(Certificate) out.Raw = in.Raw out.RawTBSCertificate = in.TBSCertificate.Raw out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.Raw out.RawSubject = in.TBSCertificate.Subject.FullBytes out.RawIssuer = in.TBSCertificate.Issuer.FullBytes out.Signature = in.SignatureValue.RightAlign() out.SignatureAlgorithm = getSignatureAlgorithmFromOID(in.TBSCertificate.SignatureAlgorithm.Algorithm) out.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm) var err os.Error out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, &in.TBSCertificate.PublicKey) if err != nil { return nil, err } if in.TBSCertificate.SerialNumber.Sign() < 0 { return nil, os.NewError("negative serial number") } out.Version = in.TBSCertificate.Version + 1 out.SerialNumber = in.TBSCertificate.SerialNumber var issuer, subject pkix.RDNSequence if _, err := asn1.Unmarshal(in.TBSCertificate.Subject.FullBytes, &subject); err != nil { return nil, err } if _, err := asn1.Unmarshal(in.TBSCertificate.Issuer.FullBytes, &issuer); err != nil { return nil, err } out.Issuer.FillFromRDNSequence(&issuer) out.Subject.FillFromRDNSequence(&subject) out.NotBefore = in.TBSCertificate.Validity.NotBefore out.NotAfter = in.TBSCertificate.Validity.NotAfter for _, e := range in.TBSCertificate.Extensions { if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { switch e.Id[3] { case 15: // RFC 5280, 4.2.1.3 var usageBits asn1.BitString _, err := asn1.Unmarshal(e.Value, &usageBits) if err == nil { var usage int for i := 0; i < 9; i++ { if usageBits.At(i) != 0 { usage |= 1 << uint(i) } } out.KeyUsage = KeyUsage(usage) continue } case 19: // RFC 5280, 4.2.1.9 var constraints basicConstraints _, err := asn1.Unmarshal(e.Value, &constraints) if err == nil { out.BasicConstraintsValid = true out.IsCA = constraints.IsCA out.MaxPathLen = constraints.MaxPathLen continue } case 17: // RFC 5280, 4.2.1.6 // SubjectAltName ::= GeneralNames // // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // // GeneralName ::= CHOICE { // otherName [0] OtherName, // rfc822Name [1] IA5String, // dNSName [2] IA5String, // x400Address [3] ORAddress, // directoryName [4] Name, // ediPartyName [5] EDIPartyName, // uniformResourceIdentifier [6] IA5String, // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } var seq asn1.RawValue _, err := asn1.Unmarshal(e.Value, &seq) if err != nil { return nil, err } if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { return nil, asn1.StructuralError{"bad SAN sequence"} } parsedName := false rest := seq.Bytes for len(rest) > 0 { var v asn1.RawValue rest, err = asn1.Unmarshal(rest, &v) if err != nil { return nil, err } switch v.Tag { case 1: out.EmailAddresses = append(out.EmailAddresses, string(v.Bytes)) parsedName = true case 2: out.DNSNames = append(out.DNSNames, string(v.Bytes)) parsedName = true } } if parsedName { continue } // If we didn't parse any of the names then we // fall through to the critical check below. case 30: // RFC 5280, 4.2.1.10 // NameConstraints ::= SEQUENCE { // permittedSubtrees [0] GeneralSubtrees OPTIONAL, // excludedSubtrees [1] GeneralSubtrees OPTIONAL } // // GeneralSubtrees ::= SEQUENCE SIZE (1..MAX) OF GeneralSubtree // // GeneralSubtree ::= SEQUENCE { // base GeneralName, // minimum [0] BaseDistance DEFAULT 0, // maximum [1] BaseDistance OPTIONAL } // // BaseDistance ::= INTEGER (0..MAX) var constraints nameConstraints _, err := asn1.Unmarshal(e.Value, &constraints) if err != nil { return nil, err } if len(constraints.Excluded) > 0 && e.Critical { return out, UnhandledCriticalExtension{} } for _, subtree := range constraints.Permitted { if subtree.Min > 0 || subtree.Max > 0 || len(subtree.Name) == 0 { if e.Critical { return out, UnhandledCriticalExtension{} } continue } out.PermittedDNSDomains = append(out.PermittedDNSDomains, subtree.Name) } continue case 35: // RFC 5280, 4.2.1.1 var a authKeyId _, err = asn1.Unmarshal(e.Value, &a) if err != nil { return nil, err } out.AuthorityKeyId = a.Id continue case 37: // RFC 5280, 4.2.1.12. Extended Key Usage // id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } // // ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId // // KeyPurposeId ::= OBJECT IDENTIFIER var keyUsage []asn1.ObjectIdentifier _, err = asn1.Unmarshal(e.Value, &keyUsage) if err != nil { return nil, err } for _, u := range keyUsage { switch { case u.Equal(oidExtKeyUsageAny): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageAny) case u.Equal(oidExtKeyUsageServerAuth): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageServerAuth) case u.Equal(oidExtKeyUsageClientAuth): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageClientAuth) case u.Equal(oidExtKeyUsageCodeSigning): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageCodeSigning) case u.Equal(oidExtKeyUsageEmailProtection): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageEmailProtection) case u.Equal(oidExtKeyUsageTimeStamping): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageTimeStamping) case u.Equal(oidExtKeyUsageOCSPSigning): out.ExtKeyUsage = append(out.ExtKeyUsage, ExtKeyUsageOCSPSigning) default: out.UnknownExtKeyUsage = append(out.UnknownExtKeyUsage, u) } } continue case 14: // RFC 5280, 4.2.1.2 var keyid []byte _, err = asn1.Unmarshal(e.Value, &keyid) if err != nil { return nil, err } out.SubjectKeyId = keyid continue case 32: // RFC 5280 4.2.1.4: Certificate Policies var policies []policyInformation if _, err = asn1.Unmarshal(e.Value, &policies); err != nil { return nil, err } out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies)) for i, policy := range policies { out.PolicyIdentifiers[i] = policy.Policy } } } if e.Critical { return out, UnhandledCriticalExtension{} } } return out, nil }
func parseCertificate(in *certificate) (*Certificate, os.Error) { out := new(Certificate) out.Raw = in.TBSCertificate.Raw out.Signature = in.SignatureValue.RightAlign() out.SignatureAlgorithm = getSignatureAlgorithmFromOID(in.TBSCertificate.SignatureAlgorithm.Algorithm) out.PublicKeyAlgorithm = getPublicKeyAlgorithmFromOID(in.TBSCertificate.PublicKey.Algorithm.Algorithm) var err os.Error out.PublicKey, err = parsePublicKey(out.PublicKeyAlgorithm, in.TBSCertificate.PublicKey.PublicKey.RightAlign()) if err != nil { return nil, err } out.Version = in.TBSCertificate.Version + 1 out.SerialNumber = in.TBSCertificate.SerialNumber.Bytes out.Issuer.fillFromRDNSequence(&in.TBSCertificate.Issuer) out.Subject.fillFromRDNSequence(&in.TBSCertificate.Subject) out.NotBefore = in.TBSCertificate.Validity.NotBefore out.NotAfter = in.TBSCertificate.Validity.NotAfter for _, e := range in.TBSCertificate.Extensions { if len(e.Id) == 4 && e.Id[0] == 2 && e.Id[1] == 5 && e.Id[2] == 29 { switch e.Id[3] { case 15: // RFC 5280, 4.2.1.3 var usageBits asn1.BitString _, err := asn1.Unmarshal(e.Value, &usageBits) if err == nil { var usage int for i := 0; i < 9; i++ { if usageBits.At(i) != 0 { usage |= 1 << uint(i) } } out.KeyUsage = KeyUsage(usage) continue } case 19: // RFC 5280, 4.2.1.9 var constriants basicConstraints _, err := asn1.Unmarshal(e.Value, &constriants) if err == nil { out.BasicConstraintsValid = true out.IsCA = constriants.IsCA out.MaxPathLen = constriants.MaxPathLen continue } case 17: // RFC 5280, 4.2.1.6 // SubjectAltName ::= GeneralNames // // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName // // GeneralName ::= CHOICE { // otherName [0] OtherName, // rfc822Name [1] IA5String, // dNSName [2] IA5String, // x400Address [3] ORAddress, // directoryName [4] Name, // ediPartyName [5] EDIPartyName, // uniformResourceIdentifier [6] IA5String, // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } var seq asn1.RawValue _, err := asn1.Unmarshal(e.Value, &seq) if err != nil { return nil, err } if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { return nil, asn1.StructuralError{"bad SAN sequence"} } parsedName := false rest := seq.Bytes for len(rest) > 0 { var v asn1.RawValue rest, err = asn1.Unmarshal(rest, &v) if err != nil { return nil, err } switch v.Tag { case 1: out.EmailAddresses = append(out.EmailAddresses, string(v.Bytes)) parsedName = true case 2: out.DNSNames = append(out.DNSNames, string(v.Bytes)) parsedName = true } } if parsedName { continue } // If we didn't parse any of the names then we // fall through to the critical check below. case 35: // RFC 5280, 4.2.1.1 var a authKeyId _, err = asn1.Unmarshal(e.Value, &a) if err != nil { return nil, err } out.AuthorityKeyId = a.Id continue case 14: // RFC 5280, 4.2.1.2 var keyid []byte _, err = asn1.Unmarshal(e.Value, &keyid) if err != nil { return nil, err } out.SubjectKeyId = keyid continue case 32: // RFC 5280 4.2.1.4: Certificate Policies var policies []policyInformation if _, err = asn1.Unmarshal(e.Value, &policies); err != nil { return nil, err } out.PolicyIdentifiers = make([]asn1.ObjectIdentifier, len(policies)) for i, policy := range policies { out.PolicyIdentifiers[i] = policy.Policy } } } if e.Critical { return out, UnhandledCriticalExtension{} } } return out, nil }