1
0
mirror of https://github.com/golang/go synced 2024-11-26 00:07:57 -07:00

crypto/x509: keep the raw Subject and Issuer.

X509 names, like everything else X509, are ludicrously general. This
change keeps the raw version of the subject and issuer around for
matching. Since certificates use a distinguished encoding, comparing
the encoding is the same as comparing the values directly. This came
up recently when parsing the NSS built-in certificates which use the
raw subject and issuer for matching trust records to certificates.

R=bradfitz
CC=golang-dev
https://golang.org/cl/5275047
This commit is contained in:
Adam Langley 2011-10-14 15:06:54 -04:00
parent 37e802a7c5
commit e74dcbeb0f
5 changed files with 47 additions and 18 deletions

View File

@ -464,11 +464,15 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
if v.Type() == rawValueType { if v.Type() == rawValueType {
rv := v.Interface().(RawValue) rv := v.Interface().(RawValue)
if len(rv.FullBytes) != 0 {
_, err = out.Write(rv.FullBytes)
} else {
err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound}) err = marshalTagAndLength(out, tagAndLength{rv.Class, rv.Tag, len(rv.Bytes), rv.IsCompound})
if err != nil { if err != nil {
return return
} }
_, err = out.Write(rv.Bytes) _, err = out.Write(rv.Bytes)
}
return return
} }

View File

@ -5,9 +5,7 @@
package x509 package x509
import ( import (
"crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"strings"
) )
// Roots is a set of certificates. // Roots is a set of certificates.
@ -26,10 +24,6 @@ func NewCertPool() *CertPool {
} }
} }
func nameToKey(name *pkix.Name) string {
return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
}
// findVerifiedParents attempts to find certificates in s which have signed the // findVerifiedParents attempts to find certificates in s which have signed the
// given certificate. If no such certificate can be found or the signature // given certificate. If no such certificate can be found or the signature
// doesn't match, it returns nil. // doesn't match, it returns nil.
@ -40,7 +34,7 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)] candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
} }
if len(candidates) == 0 { if len(candidates) == 0 {
candidates = s.byName[nameToKey(&cert.Issuer)] candidates = s.byName[string(cert.RawIssuer)]
} }
for _, c := range candidates { for _, c := range candidates {
@ -72,7 +66,7 @@ func (s *CertPool) AddCert(cert *Certificate) {
keyId := string(cert.SubjectKeyId) keyId := string(cert.SubjectKeyId)
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n) s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
} }
name := nameToKey(&cert.Subject) name := string(cert.RawSubject)
s.byName[name] = append(s.byName[name], n) s.byName[name] = append(s.byName[name], n)
} }

View File

@ -43,6 +43,8 @@ type Name struct {
Locality, Province []string Locality, Province []string
StreetAddress, PostalCode []string StreetAddress, PostalCode []string
SerialNumber, CommonName string SerialNumber, CommonName string
Names []AttributeTypeAndValue
} }
func (n *Name) FillFromRDNSequence(rdns *RDNSequence) { func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
@ -51,6 +53,7 @@ func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
continue continue
} }
atv := rdn[0] atv := rdn[0]
n.Names = append(n.Names, atv)
value, ok := atv.Value.(string) value, ok := atv.Value.(string)
if !ok { if !ok {
continue continue

View File

@ -5,6 +5,7 @@
package x509 package x509
import ( import (
"crypto/x509/pkix"
"encoding/pem" "encoding/pem"
"os" "os"
"strings" "strings"
@ -211,6 +212,10 @@ func chainToDebugString(chain []*Certificate) string {
return chainStr return chainStr
} }
func nameToKey(name *pkix.Name) string {
return strings.Join(name.Country, ",") + "/" + strings.Join(name.Organization, ",") + "/" + strings.Join(name.OrganizationalUnit, ",") + "/" + name.CommonName
}
const verisignRoot = `-----BEGIN CERTIFICATE----- const verisignRoot = `-----BEGIN CERTIFICATE-----
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz

View File

@ -138,9 +138,9 @@ type tbsCertificate struct {
Version int `asn1:"optional,explicit,default:1,tag:0"` Version int `asn1:"optional,explicit,default:1,tag:0"`
SerialNumber *big.Int SerialNumber *big.Int
SignatureAlgorithm pkix.AlgorithmIdentifier SignatureAlgorithm pkix.AlgorithmIdentifier
Issuer pkix.RDNSequence Issuer asn1.RawValue
Validity validity Validity validity
Subject pkix.RDNSequence Subject asn1.RawValue
PublicKey publicKeyInfo PublicKey publicKeyInfo
UniqueId asn1.BitString `asn1:"optional,tag:1"` UniqueId asn1.BitString `asn1:"optional,tag:1"`
SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"` SubjectUniqueId asn1.BitString `asn1:"optional,tag:2"`
@ -339,6 +339,8 @@ type Certificate struct {
Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature). Raw []byte // Complete ASN.1 DER content (certificate, signature algorithm and signature).
RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content. RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo. RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
RawSubject []byte // DER encoded Subject
RawIssuer []byte // DER encoded Issuer
Signature []byte Signature []byte
SignatureAlgorithm SignatureAlgorithm SignatureAlgorithm SignatureAlgorithm
@ -556,6 +558,8 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
out.Raw = in.Raw out.Raw = in.Raw
out.RawTBSCertificate = in.TBSCertificate.Raw out.RawTBSCertificate = in.TBSCertificate.Raw
out.RawSubjectPublicKeyInfo = in.TBSCertificate.PublicKey.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.Signature = in.SignatureValue.RightAlign()
out.SignatureAlgorithm = out.SignatureAlgorithm =
@ -575,8 +579,18 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
out.Version = in.TBSCertificate.Version + 1 out.Version = in.TBSCertificate.Version + 1
out.SerialNumber = in.TBSCertificate.SerialNumber out.SerialNumber = in.TBSCertificate.SerialNumber
out.Issuer.FillFromRDNSequence(&in.TBSCertificate.Issuer)
out.Subject.FillFromRDNSequence(&in.TBSCertificate.Subject) 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.NotBefore = in.TBSCertificate.Validity.NotBefore
out.NotAfter = in.TBSCertificate.Validity.NotAfter out.NotAfter = in.TBSCertificate.Validity.NotAfter
@ -968,14 +982,23 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
return return
} }
asn1Issuer, err := asn1.Marshal(parent.Issuer.ToRDNSequence())
if err != nil {
return
}
asn1Subject, err := asn1.Marshal(parent.Subject.ToRDNSequence())
if err != nil {
return
}
encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey} encodedPublicKey := asn1.BitString{BitLength: len(asn1PublicKey) * 8, Bytes: asn1PublicKey}
c := tbsCertificate{ c := tbsCertificate{
Version: 2, Version: 2,
SerialNumber: template.SerialNumber, SerialNumber: template.SerialNumber,
SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA}, SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
Issuer: parent.Subject.ToRDNSequence(), Issuer: asn1.RawValue{FullBytes: asn1Issuer},
Validity: validity{template.NotBefore, template.NotAfter}, Validity: validity{template.NotBefore, template.NotAfter},
Subject: template.Subject.ToRDNSequence(), Subject: asn1.RawValue{FullBytes: asn1Subject},
PublicKey: publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey}, PublicKey: publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
Extensions: extensions, Extensions: extensions,
} }