github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/crypto/x509/cert_pool.go (about) 1 // Copyright 2011 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package x509 6 7 import ( 8 "encoding/pem" 9 ) 10 11 // CertPool is a set of certificates. 12 type CertPool struct { 13 bySubjectKeyId map[string][]int 14 byName map[string][]int 15 certs []*Certificate 16 } 17 18 // NewCertPool returns a new, empty CertPool. 19 func NewCertPool() *CertPool { 20 return &CertPool{ 21 make(map[string][]int), 22 make(map[string][]int), 23 nil, 24 } 25 } 26 27 // findVerifiedParents attempts to find certificates in s which have signed the 28 // given certificate. If no such certificate can be found or the signature 29 // doesn't match, it returns nil. 30 func (s *CertPool) findVerifiedParents(cert *Certificate) (parents []int) { 31 if s == nil { 32 return 33 } 34 var candidates []int 35 36 if len(cert.AuthorityKeyId) > 0 { 37 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)] 38 } 39 if len(candidates) == 0 { 40 candidates = s.byName[string(cert.RawIssuer)] 41 } 42 43 for _, c := range candidates { 44 if cert.CheckSignatureFrom(s.certs[c]) == nil { 45 parents = append(parents, c) 46 } 47 } 48 49 return 50 } 51 52 // AddCert adds a certificate to a pool. 53 func (s *CertPool) AddCert(cert *Certificate) { 54 if cert == nil { 55 panic("adding nil Certificate to CertPool") 56 } 57 58 // Check that the certificate isn't being added twice. 59 for _, c := range s.certs { 60 if c.Equal(cert) { 61 return 62 } 63 } 64 65 n := len(s.certs) 66 s.certs = append(s.certs, cert) 67 68 if len(cert.SubjectKeyId) > 0 { 69 keyId := string(cert.SubjectKeyId) 70 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n) 71 } 72 name := string(cert.RawSubject) 73 s.byName[name] = append(s.byName[name], n) 74 } 75 76 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. 77 // It appends any certificates found to s and returns true if any certificates 78 // were successfully parsed. 79 // 80 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set 81 // of root CAs in a format suitable for this function. 82 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { 83 for len(pemCerts) > 0 { 84 var block *pem.Block 85 block, pemCerts = pem.Decode(pemCerts) 86 if block == nil { 87 break 88 } 89 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { 90 continue 91 } 92 93 cert, err := ParseCertificate(block.Bytes) 94 if err != nil { 95 continue 96 } 97 98 s.AddCert(cert) 99 ok = true 100 } 101 102 return 103 } 104 105 // Subjects returns a list of the DER-encoded subjects of 106 // all of the certificates in the pool. 107 func (s *CertPool) Subjects() (res [][]byte) { 108 res = make([][]byte, len(s.certs)) 109 for i, c := range s.certs { 110 res[i] = c.RawSubject 111 } 112 return 113 }