gitee.com/lh-her-team/common@v1.5.1/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 bySubjectKeyId: make(map[string][]int), 22 byName: make(map[string][]int), 23 } 24 } 25 26 // nolint: unused 27 func (s *CertPool) copy() *CertPool { 28 p := &CertPool{ 29 bySubjectKeyId: make(map[string][]int, len(s.bySubjectKeyId)), 30 byName: make(map[string][]int, len(s.byName)), 31 certs: make([]*Certificate, len(s.certs)), 32 } 33 for k, v := range s.bySubjectKeyId { 34 indexes := make([]int, len(v)) 35 copy(indexes, v) 36 p.bySubjectKeyId[k] = indexes 37 } 38 for k, v := range s.byName { 39 indexes := make([]int, len(v)) 40 copy(indexes, v) 41 p.byName[k] = indexes 42 } 43 copy(p.certs, s.certs) 44 return p 45 } 46 47 // findPotentialParents returns the indexes of certificates in s which might 48 // have signed cert. The caller must not modify the returned slice. 49 func (s *CertPool) findPotentialParents(cert *Certificate) []int { 50 if s == nil { 51 return nil 52 } 53 var candidates []int 54 if len(cert.AuthorityKeyId) > 0 { 55 candidates = s.bySubjectKeyId[string(cert.AuthorityKeyId)] 56 } 57 if len(candidates) == 0 { 58 candidates = s.byName[string(cert.RawIssuer)] 59 } 60 return candidates 61 } 62 63 func (s *CertPool) contains(cert *Certificate) bool { 64 if s == nil { 65 return false 66 } 67 candidates := s.byName[string(cert.RawSubject)] 68 for _, c := range candidates { 69 if s.certs[c].Equal(cert) { 70 return true 71 } 72 } 73 return false 74 } 75 76 // AddCert adds a certificate to a pool. 77 func (s *CertPool) AddCert(cert *Certificate) { 78 if cert == nil { 79 panic("adding nil Certificate to CertPool") 80 } 81 // Check that the certificate isn't being added twice. 82 if s.contains(cert) { 83 return 84 } 85 n := len(s.certs) 86 s.certs = append(s.certs, cert) 87 if len(cert.SubjectKeyId) > 0 { 88 keyId := string(cert.SubjectKeyId) 89 s.bySubjectKeyId[keyId] = append(s.bySubjectKeyId[keyId], n) 90 } 91 name := string(cert.RawSubject) 92 s.byName[name] = append(s.byName[name], n) 93 } 94 95 // AppendCertsFromPEM attempts to parse a series of PEM encoded certificates. 96 // It appends any certificates found to s and reports whether any certificates 97 // were successfully parsed. 98 // 99 // On many Linux systems, /etc/ssl/cert.pem will contain the system wide set 100 // of root CAs in a format suitable for this function. 101 func (s *CertPool) AppendCertsFromPEM(pemCerts []byte) (ok bool) { 102 for len(pemCerts) > 0 { 103 var block *pem.Block 104 block, pemCerts = pem.Decode(pemCerts) 105 if block == nil { 106 break 107 } 108 if block.Type != "CERTIFICATE" || len(block.Headers) != 0 { 109 continue 110 } 111 cert, err := ParseCertificate(block.Bytes) 112 if err != nil { 113 continue 114 } 115 s.AddCert(cert) 116 ok = true 117 } 118 return 119 } 120 121 // Subjects returns a list of the DER-encoded subjects of 122 // all of the certificates in the pool. 123 func (s *CertPool) Subjects() [][]byte { 124 res := make([][]byte, len(s.certs)) 125 for i, c := range s.certs { 126 res[i] = c.RawSubject 127 } 128 return res 129 }