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  }