github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/p2p/secure/secure_manager.go (about)

     1  package secure
     2  
     3  import (
     4  	"bytes"
     5  	"crypto/x509"
     6  	"crypto/x509/pkix"
     7  	"encoding/asn1"
     8  	"errors"
     9  	"fmt"
    10  	"github.com/bigzoro/my_simplechain/common"
    11  	"github.com/bigzoro/my_simplechain/log"
    12  	"github.com/bigzoro/my_simplechain/rlp"
    13  	mapset "github.com/deckarep/golang-set"
    14  	"golang.org/x/crypto/sha3"
    15  	"io/ioutil"
    16  	"math/big"
    17  	"os"
    18  	"path/filepath"
    19  	"reflect"
    20  	"strings"
    21  	"time"
    22  )
    23  
    24  type SecureConfig struct {
    25  	//root certificates
    26  	TlsRootCerts [][]byte
    27  	// List of TLS intermediate certificates;
    28  	TlsIntermediateCerts [][]byte
    29  	//revocation lists
    30  	RevocationList [][]byte
    31  }
    32  type SecureManager struct {
    33  	opts *x509.VerifyOptions
    34  	// list of CA TLS certs we trust ,setupTLSCAs
    35  	TLSRootCerts [][]byte
    36  	// list of intermediate TLS certs we trust,setupTLSCAs
    37  	TLSIntermediateCerts [][]byte
    38  	// list of certificate revocation lists,setupCRLs
    39  	CRL       []*pkix.CertificateList
    40  	crlHashes mapset.Set
    41  }
    42  
    43  func rlpHash(x interface{}) (h common.Hash) {
    44  	hw := sha3.NewLegacyKeccak256()
    45  	rlp.Encode(hw, x)
    46  	hw.Sum(h[:0])
    47  	return h
    48  }
    49  
    50  // 设置吊销证书
    51  func (s *SecureManager) setupCRLs(conf *SecureConfig) error {
    52  	s.crlHashes = mapset.NewSet()
    53  	// setup the CRL (if present)
    54  	s.CRL = make([]*pkix.CertificateList, len(conf.RevocationList))
    55  	for i, CRLBytes := range conf.RevocationList {
    56  		hash := rlpHash(CRLBytes)
    57  		s.crlHashes.Add(hash)
    58  		crl, err := x509.ParseCRL(CRLBytes)
    59  		if err != nil {
    60  			return errors.New(fmt.Sprintf("could not parse Content %v", err))
    61  		}
    62  		// Massage the ECDSA signature values
    63  		if isECDSASignatureAlgorithm(crl.SignatureAlgorithm.Algorithm) {
    64  			r, s, err := UnmarshalECDSASignature(crl.SignatureValue.RightAlign())
    65  			if err != nil {
    66  				return err
    67  			}
    68  			sig, err := MarshalECDSASignature(r, s)
    69  			if err != nil {
    70  				return err
    71  			}
    72  			crl.SignatureValue = asn1.BitString{Bytes: sig, BitLength: 8 * len(sig)}
    73  		}
    74  		s.CRL[i] = crl
    75  	}
    76  	return nil
    77  }
    78  func (s *SecureManager) SaveCRL(dir string, CRLBytes []byte) ([]*big.Int, error) {
    79  	hash := rlpHash(CRLBytes)
    80  	if s.crlHashes != nil && s.crlHashes.Contains(hash) {
    81  		return nil, errors.New("crl exists")
    82  	}
    83  	crl, err := x509.ParseCRL(CRLBytes)
    84  	if err != nil {
    85  		return nil, errors.New(fmt.Sprintf("could not parse Content %v", err))
    86  	}
    87  	// Massage the ECDSA signature values
    88  	if isECDSASignatureAlgorithm(crl.SignatureAlgorithm.Algorithm) {
    89  		r, s, err := UnmarshalECDSASignature(crl.SignatureValue.RightAlign())
    90  		if err != nil {
    91  			return nil, err
    92  		}
    93  		sig, err := MarshalECDSASignature(r, s)
    94  		if err != nil {
    95  			return nil, err
    96  		}
    97  		crl.SignatureValue = asn1.BitString{Bytes: sig, BitLength: 8 * len(sig)}
    98  	}
    99  	serialNumbers := make([]*big.Int, 0)
   100  	for _, rc := range crl.TBSCertList.RevokedCertificates {
   101  		serialNumbers = append(serialNumbers, rc.SerialNumber)
   102  	}
   103  	s.CRL = append(s.CRL, crl)
   104  	CRLsDir := filepath.Join(dir, CRLsFolder)
   105  	if !PathExists(CRLsDir) {
   106  		os.MkdirAll(CRLsDir, os.ModePerm)
   107  	}
   108  	fileName := fmt.Sprintf("crl_%d.pem", time.Now().Nanosecond())
   109  	fileName = filepath.Join(CRLsDir, fileName)
   110  	log.Info("SecureManager receive crl data,save in", "path", fileName)
   111  	if err = ioutil.WriteFile(fileName, CRLBytes, 0666); err != nil {
   112  		return nil, err
   113  	}
   114  	return serialNumbers, nil
   115  }
   116  func PathExists(path string) bool {
   117  	_, err := os.Stat(path)
   118  	if err == nil {
   119  		return true
   120  	}
   121  	if os.IsNotExist(err) {
   122  		return false
   123  	}
   124  	return false
   125  }
   126  
   127  // 包括根证书和根证书
   128  func (s *SecureManager) setupTLSCAs(conf *SecureConfig) error {
   129  	opts := &x509.VerifyOptions{Roots: x509.NewCertPool(), Intermediates: x509.NewCertPool()}
   130  	// Load TLS root and intermediate CA identities
   131  	s.TLSRootCerts = make([][]byte, len(conf.TlsRootCerts))
   132  	rootCerts := make([]*x509.Certificate, len(conf.TlsRootCerts))
   133  	for i, trustedCert := range conf.TlsRootCerts {
   134  		cert, err := GetCertFromPem(trustedCert)
   135  		if err != nil {
   136  			return err
   137  		}
   138  		rootCerts[i] = cert
   139  		s.TLSRootCerts[i] = trustedCert
   140  		opts.Roots.AddCert(cert)
   141  	}
   142  	// make and fill the set of intermediate certs (if present)
   143  	s.TLSIntermediateCerts = make([][]byte, len(conf.TlsIntermediateCerts))
   144  	intermediateCerts := make([]*x509.Certificate, len(conf.TlsIntermediateCerts))
   145  	for i, trustedCert := range conf.TlsIntermediateCerts {
   146  		cert, err := GetCertFromPem(trustedCert)
   147  		if err != nil {
   148  			return err
   149  		}
   150  		intermediateCerts[i] = cert
   151  		s.TLSIntermediateCerts[i] = trustedCert
   152  		opts.Intermediates.AddCert(cert)
   153  	}
   154  	s.opts = opts
   155  	// ensure that our CAs are properly formed and that they are valid
   156  	for _, cert := range append(append([]*x509.Certificate{}, rootCerts...), intermediateCerts...) {
   157  		if cert == nil {
   158  			continue
   159  		}
   160  		if !cert.IsCA {
   161  			return errors.New(fmt.Sprintf("CA Certificate did not have the CA attribute, (SN: %x)", cert.SerialNumber))
   162  		}
   163  		if _, err := getSubjectKeyIdentifierFromCert(cert); err != nil {
   164  			return errors.New(fmt.Sprintf("%v CA Certificate problem with Subject Key Identifier extension, (SN: %x)", err, cert.SerialNumber))
   165  		}
   166  
   167  		if err := s.validateTLSCAIdentity(cert, opts); err != nil {
   168  			return errors.New(fmt.Sprintf("%v CA Certificate is not valid, (SN: %s)", err, cert.SerialNumber))
   169  		}
   170  	}
   171  	return nil
   172  }
   173  
   174  func (s *SecureManager) validateTLSCAIdentity(cert *x509.Certificate, opts *x509.VerifyOptions) error {
   175  	if !cert.IsCA {
   176  		return errors.New("only CA identities can be validated")
   177  	}
   178  	validationChain, err := s.getUniqueValidationChain(cert, *opts)
   179  	if err != nil {
   180  		return errors.New(fmt.Sprintf("%v could not obtain certification chain", err))
   181  	}
   182  	if len(validationChain) == 1 {
   183  		return nil
   184  	}
   185  	return s.validateCertAgainstChain(cert, validationChain)
   186  }
   187  
   188  func (s *SecureManager) getUniqueValidationChain(cert *x509.Certificate, opts x509.VerifyOptions) ([]*x509.Certificate, error) {
   189  	// ask golang to validate the cert for us based on the options that we've built at setup time
   190  	if s.opts == nil {
   191  		return nil, errors.New("the supplied identity has no verify options")
   192  	}
   193  	validationChains, err := cert.Verify(opts)
   194  	if err != nil {
   195  		return nil, errors.New(fmt.Sprintf("%v the supplied identity is not valid", err))
   196  	}
   197  
   198  	// we only support a single validation chain;
   199  	// if there's more than one then there might
   200  	// be unclarity about who owns the identity
   201  	if len(validationChains) != 1 {
   202  		return nil, errors.New(fmt.Sprintf("%v this MSP only supports a single validation chain, got %d", err, len(validationChains)))
   203  	}
   204  
   205  	// Make the additional verification checks that were done in Go 1.14.
   206  	err = verifyLegacyNameConstraints(validationChains[0])
   207  	if err != nil {
   208  		return nil, errors.New(fmt.Sprintf("%v the supplied identity is not valid", err))
   209  	}
   210  
   211  	return validationChains[0], nil
   212  }
   213  
   214  var (
   215  	oidExtensionSubjectAltName  = asn1.ObjectIdentifier{2, 5, 29, 17}
   216  	oidExtensionNameConstraints = asn1.ObjectIdentifier{2, 5, 29, 30}
   217  )
   218  
   219  // verifyLegacyNameConstraints exercises the name constraint validation rules
   220  // that were part of the certificate verification process in Go 1.14.
   221  //
   222  // If a signing certificate contains a name constratint, the leaf certificate
   223  // does not include SAN extensions, and the leaf's common name looks like a
   224  // host name, the validation would fail with an x509.CertificateInvalidError
   225  // and a rason of x509.NameConstraintsWithoutSANs.
   226  func verifyLegacyNameConstraints(chain []*x509.Certificate) error {
   227  	if len(chain) < 2 {
   228  		return nil
   229  	}
   230  
   231  	// Leaf certificates with SANs are fine.
   232  	if oidInExtensions(oidExtensionSubjectAltName, chain[0].Extensions) {
   233  		return nil
   234  	}
   235  	// Leaf certificates without a hostname in CN are fine.
   236  	if !validHostname(chain[0].Subject.CommonName) {
   237  		return nil
   238  	}
   239  	// If an intermediate or root have a name constraint, validation
   240  	// would fail in Go 1.14.
   241  	for _, c := range chain[1:] {
   242  		if oidInExtensions(oidExtensionNameConstraints, c.Extensions) {
   243  			return x509.CertificateInvalidError{Cert: chain[0], Reason: x509.NameConstraintsWithoutSANs}
   244  		}
   245  	}
   246  	return nil
   247  }
   248  
   249  func oidInExtensions(oid asn1.ObjectIdentifier, exts []pkix.Extension) bool {
   250  	for _, ext := range exts {
   251  		if ext.Id.Equal(oid) {
   252  			return true
   253  		}
   254  	}
   255  	return false
   256  }
   257  
   258  // validHostname reports whether host is a valid hostname that can be matched or
   259  // matched against according to RFC 6125 2.2, with some leniency to accommodate
   260  // legacy values.
   261  //
   262  // This implementation is sourced from the standard library.
   263  func validHostname(host string) bool {
   264  	host = strings.TrimSuffix(host, ".")
   265  
   266  	if len(host) == 0 {
   267  		return false
   268  	}
   269  
   270  	for i, part := range strings.Split(host, ".") {
   271  		if part == "" {
   272  			// Empty label.
   273  			return false
   274  		}
   275  		if i == 0 && part == "*" {
   276  			// Only allow full left-most wildcards, as those are the only ones
   277  			// we match, and matching literal '*' characters is probably never
   278  			// the expected behavior.
   279  			continue
   280  		}
   281  		for j, c := range part {
   282  			if 'a' <= c && c <= 'z' {
   283  				continue
   284  			}
   285  			if '0' <= c && c <= '9' {
   286  				continue
   287  			}
   288  			if 'A' <= c && c <= 'Z' {
   289  				continue
   290  			}
   291  			if c == '-' && j != 0 {
   292  				continue
   293  			}
   294  			if c == '_' || c == ':' {
   295  				// Not valid characters in hostnames, but commonly
   296  				// found in deployments outside the WebPKI.
   297  				continue
   298  			}
   299  			return false
   300  		}
   301  	}
   302  
   303  	return true
   304  }
   305  func (s *SecureManager) validateCertAgainstChain(cert *x509.Certificate, validationChain []*x509.Certificate) error {
   306  	// here we know that the identity is valid; now we have to check whether it has been revoked
   307  
   308  	// identify the SKI of the CA that signed this cert
   309  	SKI, err := getSubjectKeyIdentifierFromCert(validationChain[1])
   310  	if err != nil {
   311  		return errors.New(fmt.Sprintf("%vcould not obtain Subject Key Identifier for signer cert", err))
   312  	}
   313  
   314  	// check whether one of the CRLs we have has this cert's
   315  	// SKI as its AuthorityKeyIdentifier
   316  	for _, crl := range s.CRL {
   317  		aki, err := getAuthorityKeyIdentifierFromCrl(crl)
   318  		if err != nil {
   319  			return errors.New(fmt.Sprintf("%v could not obtain Authority Key Identifier for crl", err))
   320  		}
   321  
   322  		// check if the SKI of the cert that signed us matches the AKI of any of the CRLs
   323  		if bytes.Equal(aki, SKI) {
   324  			// we have a CRL, check whether the serial number is revoked
   325  			for _, rc := range crl.TBSCertList.RevokedCertificates {
   326  				if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 {
   327  					// We have found a CRL whose AKI matches the SKI of
   328  					// the CA (root or intermediate) that signed the
   329  					// certificate that is under validation. As a
   330  					// precaution, we verify that said CA is also the
   331  					// signer of this CRL.
   332  					err = validationChain[1].CheckCRLSignature(crl)
   333  					if err != nil {
   334  						// the CA cert that signed the certificate
   335  						// that is under validation did not sign the
   336  						// candidate CRL - skip
   337  						log.Error(fmt.Sprintf("invalid signature over the identified CRL, error %+v", err))
   338  						continue
   339  					}
   340  
   341  					// A CRL also includes a time of revocation so that
   342  					// the CA can say "this cert is to be revoked starting
   343  					// from this time"; however here we just assume that
   344  					// revocation applies instantaneously from the time
   345  					// the MSP config is committed and used so we will not
   346  					// make use of that field
   347  					return errors.New("the certificate has been revoked")
   348  				}
   349  			}
   350  		}
   351  	}
   352  
   353  	return nil
   354  }
   355  
   356  type authorityKeyIdentifier struct {
   357  	KeyIdentifier             []byte  `asn1:"optional,tag:0"`
   358  	AuthorityCertIssuer       []byte  `asn1:"optional,tag:1"`
   359  	AuthorityCertSerialNumber big.Int `asn1:"optional,tag:2"`
   360  }
   361  
   362  // getAuthorityKeyIdentifierFromCrl returns the Authority Key Identifier
   363  // for the supplied CRL. The authority key identifier can be used to identify
   364  // the public key corresponding to the private key which was used to sign the CRL.
   365  func getAuthorityKeyIdentifierFromCrl(crl *pkix.CertificateList) ([]byte, error) {
   366  	aki := authorityKeyIdentifier{}
   367  	for _, ext := range crl.TBSCertList.Extensions {
   368  		// Authority Key Identifier is identified by the following ASN.1 tag
   369  		// authorityKeyIdentifier (2 5 29 35) (see https://tools.ietf.org/html/rfc3280.html)
   370  		if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 35}) {
   371  			_, err := asn1.Unmarshal(ext.Value, &aki)
   372  			if err != nil {
   373  				return nil, errors.New(fmt.Sprintf("%vfailed to unmarshal AKI", err))
   374  			}
   375  
   376  			return aki.KeyIdentifier, nil
   377  		}
   378  	}
   379  
   380  	return nil, errors.New("authorityKeyIdentifier not found in certificate")
   381  }
   382  
   383  func (s *SecureManager) validateCertAgainst(cert *x509.Certificate) error {
   384  	// check whether one of the CRLs we have has this cert's
   385  	for _, crl := range s.CRL {
   386  		// we have a CRL, check whether the serial number is revoked
   387  		for _, rc := range crl.TBSCertList.RevokedCertificates {
   388  			if rc.SerialNumber.Cmp(cert.SerialNumber) == 0 {
   389  				return errors.New("the certificate has been revoked")
   390  			}
   391  		}
   392  	}
   393  	return nil
   394  }