mirror of
https://github.com/golang/go
synced 2024-11-13 17:10:21 -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:
parent
37e802a7c5
commit
e74dcbeb0f
@ -464,11 +464,15 @@ func marshalField(out *forkableWriter, v reflect.Value, params fieldParameters)
|
||||
|
||||
if v.Type() == rawValueType {
|
||||
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})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_, err = out.Write(rv.Bytes)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -5,9 +5,7 @@
|
||||
package x509
|
||||
|
||||
import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 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
|
||||
// given certificate. If no such certificate can be found or the signature
|
||||
// doesn't match, it returns nil.
|
||||
@ -40,7 +34,7 @@ func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) {
|
||||
candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)]
|
||||
}
|
||||
if len(candidates) == 0 {
|
||||
candidates = s.byName[nameToKey(&cert.Issuer)]
|
||||
candidates = s.byName[string(cert.RawIssuer)]
|
||||
}
|
||||
|
||||
for _, c := range candidates {
|
||||
@ -72,7 +66,7 @@ func (s *CertPool) AddCert(cert *Certificate) {
|
||||
keyId := string(cert.SubjectKeyId)
|
||||
s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n)
|
||||
}
|
||||
name := nameToKey(&cert.Subject)
|
||||
name := string(cert.RawSubject)
|
||||
s.byName[name] = append(s.byName[name], n)
|
||||
}
|
||||
|
||||
|
@ -43,6 +43,8 @@ type Name struct {
|
||||
Locality, Province []string
|
||||
StreetAddress, PostalCode []string
|
||||
SerialNumber, CommonName string
|
||||
|
||||
Names []AttributeTypeAndValue
|
||||
}
|
||||
|
||||
func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
|
||||
@ -51,6 +53,7 @@ func (n *Name) FillFromRDNSequence(rdns *RDNSequence) {
|
||||
continue
|
||||
}
|
||||
atv := rdn[0]
|
||||
n.Names = append(n.Names, atv)
|
||||
value, ok := atv.Value.(string)
|
||||
if !ok {
|
||||
continue
|
||||
|
@ -5,6 +5,7 @@
|
||||
package x509
|
||||
|
||||
import (
|
||||
"crypto/x509/pkix"
|
||||
"encoding/pem"
|
||||
"os"
|
||||
"strings"
|
||||
@ -211,6 +212,10 @@ func chainToDebugString(chain []*Certificate) string {
|
||||
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-----
|
||||
MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkG
|
||||
A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
|
||||
|
@ -138,9 +138,9 @@ type tbsCertificate struct {
|
||||
Version int `asn1:"optional,explicit,default:1,tag:0"`
|
||||
SerialNumber *big.Int
|
||||
SignatureAlgorithm pkix.AlgorithmIdentifier
|
||||
Issuer pkix.RDNSequence
|
||||
Issuer asn1.RawValue
|
||||
Validity validity
|
||||
Subject pkix.RDNSequence
|
||||
Subject asn1.RawValue
|
||||
PublicKey publicKeyInfo
|
||||
UniqueId asn1.BitString `asn1:"optional,tag:1"`
|
||||
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).
|
||||
RawTBSCertificate []byte // Certificate part of raw ASN.1 DER content.
|
||||
RawSubjectPublicKeyInfo []byte // DER encoded SubjectPublicKeyInfo.
|
||||
RawSubject []byte // DER encoded Subject
|
||||
RawIssuer []byte // DER encoded Issuer
|
||||
|
||||
Signature []byte
|
||||
SignatureAlgorithm SignatureAlgorithm
|
||||
@ -556,6 +558,8 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
|
||||
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 =
|
||||
@ -575,8 +579,18 @@ func parseCertificate(in *certificate) (*Certificate, os.Error) {
|
||||
|
||||
out.Version = in.TBSCertificate.Version + 1
|
||||
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.NotAfter = in.TBSCertificate.Validity.NotAfter
|
||||
|
||||
@ -968,14 +982,23 @@ func CreateCertificate(rand io.Reader, template, parent *Certificate, pub *rsa.P
|
||||
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}
|
||||
c := tbsCertificate{
|
||||
Version: 2,
|
||||
SerialNumber: template.SerialNumber,
|
||||
SignatureAlgorithm: pkix.AlgorithmIdentifier{Algorithm: oidSHA1WithRSA},
|
||||
Issuer: parent.Subject.ToRDNSequence(),
|
||||
Issuer: asn1.RawValue{FullBytes: asn1Issuer},
|
||||
Validity: validity{template.NotBefore, template.NotAfter},
|
||||
Subject: template.Subject.ToRDNSequence(),
|
||||
Subject: asn1.RawValue{FullBytes: asn1Subject},
|
||||
PublicKey: publicKeyInfo{nil, pkix.AlgorithmIdentifier{Algorithm: oidRSA}, encodedPublicKey},
|
||||
Extensions: extensions,
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user