github.com/turingchain2020/turingchain@v1.1.21/executor/authority/core/ecdsaimpl.go (about)

     1  // Copyright Turing Corp. 2018 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 core
     6  
     7  import (
     8  	"bytes"
     9  	"crypto/x509"
    10  	"crypto/x509/pkix"
    11  	"encoding/asn1"
    12  	"encoding/pem"
    13  	"errors"
    14  	"fmt"
    15  	"math/big"
    16  	"reflect"
    17  	"time"
    18  
    19  	"github.com/turingchain2020/turingchain/executor/authority/utils"
    20  
    21  	"crypto/ecdsa"
    22  
    23  	log "github.com/turingchain2020/turingchain/common/log/log15"
    24  	secp256r1_util "github.com/turingchain2020/turingchain/system/crypto/secp256r1"
    25  	"github.com/turingchain2020/turingchain/types"
    26  )
    27  
    28  var authLogger = log.New("module", "authority")
    29  
    30  type ecdsaValidator struct {
    31  	rootCerts []*x509.Certificate
    32  
    33  	intermediateCerts []*x509.Certificate
    34  
    35  	certificationTreeInternalNodesMap map[string]bool
    36  
    37  	opts *x509.VerifyOptions
    38  
    39  	CRL []*pkix.CertificateList
    40  }
    41  
    42  // NewEcdsaValidator 创建ecdsa校验器
    43  func NewEcdsaValidator() Validator {
    44  	return &ecdsaValidator{}
    45  }
    46  
    47  func (validator *ecdsaValidator) getCertFromPem(idBytes []byte) (*x509.Certificate, error) {
    48  	if idBytes == nil {
    49  		return nil, fmt.Errorf("getIdentityFromConf error: nil idBytes")
    50  	}
    51  
    52  	pemCert, _ := pem.Decode(idBytes)
    53  	if pemCert == nil {
    54  		return nil, fmt.Errorf("getIdentityFromBytes error: could not decode pem bytes [%v]", idBytes)
    55  	}
    56  
    57  	var cert *x509.Certificate
    58  	cert, err := x509.ParseCertificate(pemCert.Bytes)
    59  	if err != nil {
    60  		return nil, fmt.Errorf("getIdentityFromBytes error: failed to parse x509 cert, err %s", err)
    61  	}
    62  
    63  	return cert, nil
    64  }
    65  
    66  type authorityKeyIdentifier struct {
    67  	KeyIdentifier             []byte  `asn1:"optional,tag:0"`
    68  	AuthorityCertIssuer       []byte  `asn1:"optional,tag:1"`
    69  	AuthorityCertSerialNumber big.Int `asn1:"optional,tag:2"`
    70  }
    71  
    72  func getAuthorityKeyIdentifierFromCrl(crl *pkix.CertificateList) ([]byte, error) {
    73  	aki := authorityKeyIdentifier{}
    74  
    75  	for _, ext := range crl.TBSCertList.Extensions {
    76  		if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 35}) {
    77  			_, err := asn1.Unmarshal(ext.Value, &aki)
    78  			if err != nil {
    79  				return nil, fmt.Errorf("Failed to unmarshal AKI, error %s", err)
    80  			}
    81  
    82  			return aki.KeyIdentifier, nil
    83  		}
    84  	}
    85  
    86  	return nil, errors.New("authorityKeyIdentifier not found in certificate")
    87  }
    88  
    89  func getSubjectKeyIdentifierFromCert(cert *x509.Certificate) ([]byte, error) {
    90  	var SKI []byte
    91  
    92  	for _, ext := range cert.Extensions {
    93  		if reflect.DeepEqual(ext.Id, asn1.ObjectIdentifier{2, 5, 29, 14}) {
    94  			_, err := asn1.Unmarshal(ext.Value, &SKI)
    95  			if err != nil {
    96  				return nil, fmt.Errorf("Failed to unmarshal Subject Key Identifier, err %s", err)
    97  			}
    98  
    99  			return SKI, nil
   100  		}
   101  	}
   102  
   103  	return nil, errors.New("subjectKeyIdentifier not found in certificate")
   104  }
   105  
   106  func isCACert(cert *x509.Certificate) bool {
   107  	_, err := getSubjectKeyIdentifierFromCert(cert)
   108  	if err != nil {
   109  		return false
   110  	}
   111  
   112  	if !cert.IsCA {
   113  		return false
   114  	}
   115  
   116  	return true
   117  }
   118  
   119  func (validator *ecdsaValidator) Setup(conf *AuthConfig) error {
   120  	if conf == nil {
   121  		return fmt.Errorf("Setup error: nil conf reference")
   122  	}
   123  
   124  	if err := validator.setupCAs(conf); err != nil {
   125  		return err
   126  	}
   127  
   128  	if err := validator.setupCRLs(conf); err != nil {
   129  		return err
   130  	}
   131  
   132  	if err := validator.finalizeSetupCAs(conf); err != nil {
   133  		return err
   134  	}
   135  
   136  	return nil
   137  }
   138  
   139  func (validator *ecdsaValidator) Validate(certByte []byte, pubKey []byte) error {
   140  	authLogger.Debug("validating certificate")
   141  
   142  	cert, err := validator.getCertFromPem(certByte)
   143  	if err != nil {
   144  		return fmt.Errorf("ParseCertificate failed %s", err)
   145  	}
   146  
   147  	certPubKey, ok := cert.PublicKey.(*ecdsa.PublicKey)
   148  	if !ok {
   149  		return fmt.Errorf("Error publick key type in transaction. expect ECDSA")
   150  	}
   151  
   152  	if !bytes.Equal(pubKey, secp256r1_util.SerializePublicKeyCompressed(certPubKey)) {
   153  		return fmt.Errorf("Invalid public key")
   154  	}
   155  
   156  	cert, err = validator.sanitizeCert(cert)
   157  	if err != nil {
   158  		return fmt.Errorf("Sanitize certification failed. err %s", err)
   159  	}
   160  
   161  	validationChain, err := validator.getCertificationChain(cert)
   162  	if err != nil {
   163  		return fmt.Errorf("Could not obtain certification chain, err %s", err)
   164  	}
   165  
   166  	err = validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
   167  	if err != nil {
   168  		return fmt.Errorf("Could not validate identity against certification chain, err %s", err)
   169  	}
   170  
   171  	return nil
   172  }
   173  
   174  func (validator *ecdsaValidator) getCertificationChain(cert *x509.Certificate) ([]*x509.Certificate, error) {
   175  	if validator.opts == nil {
   176  		return nil, errors.New("Invalid validator instance")
   177  	}
   178  
   179  	if cert.IsCA {
   180  		return nil, errors.New("A CA certificate cannot be used directly")
   181  	}
   182  
   183  	return validator.getValidationChain(cert, false)
   184  }
   185  
   186  func (validator *ecdsaValidator) getUniqueValidationChain(cert *x509.Certificate, opts x509.VerifyOptions) ([]*x509.Certificate, error) {
   187  	if validator.opts == nil {
   188  		return nil, fmt.Errorf("The supplied identity has no verify options")
   189  	}
   190  	validationChains, err := cert.Verify(opts)
   191  	if err != nil {
   192  		return nil, fmt.Errorf("The supplied identity is not valid, Verify() returned %s", err)
   193  	}
   194  
   195  	if len(validationChains) != 1 {
   196  		return nil, fmt.Errorf("Only supports a single validation chain, got %d", len(validationChains))
   197  	}
   198  
   199  	return validationChains[0], nil
   200  }
   201  
   202  func (validator *ecdsaValidator) getValidationChain(cert *x509.Certificate, isIntermediateChain bool) ([]*x509.Certificate, error) {
   203  	validationChain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   204  	if err != nil {
   205  		return nil, fmt.Errorf("Failed getting validation chain %s", err)
   206  	}
   207  
   208  	if len(validationChain) < 2 {
   209  		return nil, fmt.Errorf("Expected a chain of length at least 2, got %d", len(validationChain))
   210  	}
   211  
   212  	parentPosition := 1
   213  	if isIntermediateChain {
   214  		parentPosition = 0
   215  	}
   216  	if validator.certificationTreeInternalNodesMap[string(validationChain[parentPosition].Raw)] {
   217  		return nil, fmt.Errorf("Invalid validation chain. Parent certificate should be a leaf of the certification tree [%v]", cert.Raw)
   218  	}
   219  	return validationChain, nil
   220  }
   221  
   222  func (validator *ecdsaValidator) setupCAs(conf *AuthConfig) error {
   223  	if len(conf.RootCerts) == 0 {
   224  		return errors.New("Expected at least one CA certificate")
   225  	}
   226  
   227  	validator.opts = &x509.VerifyOptions{Roots: x509.NewCertPool(), Intermediates: x509.NewCertPool()}
   228  	for _, v := range conf.RootCerts {
   229  		cert, err := validator.getCertFromPem(v)
   230  		if err != nil {
   231  			return err
   232  		}
   233  		validator.opts.Roots.AddCert(cert)
   234  	}
   235  	for _, v := range conf.IntermediateCerts {
   236  		cert, err := validator.getCertFromPem(v)
   237  		if err != nil {
   238  			return err
   239  		}
   240  		validator.opts.Intermediates.AddCert(cert)
   241  	}
   242  
   243  	validator.rootCerts = make([]*x509.Certificate, len(conf.RootCerts))
   244  	for i, trustedCert := range conf.RootCerts {
   245  		cert, err := validator.getCertFromPem(trustedCert)
   246  		if err != nil {
   247  			return err
   248  		}
   249  		cert, err = validator.sanitizeCert(cert)
   250  		if err != nil {
   251  			return err
   252  		}
   253  
   254  		validator.rootCerts[i] = cert
   255  	}
   256  
   257  	validator.intermediateCerts = make([]*x509.Certificate, len(conf.IntermediateCerts))
   258  	for i, trustedCert := range conf.IntermediateCerts {
   259  		cert, err := validator.getCertFromPem(trustedCert)
   260  		if err != nil {
   261  			return err
   262  		}
   263  		cert, err = validator.sanitizeCert(cert)
   264  		if err != nil {
   265  			return err
   266  		}
   267  
   268  		validator.intermediateCerts[i] = cert
   269  	}
   270  
   271  	validator.opts = &x509.VerifyOptions{Roots: x509.NewCertPool(), Intermediates: x509.NewCertPool()}
   272  	for _, cert := range validator.rootCerts {
   273  		validator.opts.Roots.AddCert(cert)
   274  	}
   275  	for _, cert := range validator.intermediateCerts {
   276  		validator.opts.Intermediates.AddCert(cert)
   277  	}
   278  
   279  	return nil
   280  }
   281  
   282  func (validator *ecdsaValidator) setupCRLs(conf *AuthConfig) error {
   283  	validator.CRL = make([]*pkix.CertificateList, len(conf.RevocationList))
   284  	for i, crlbytes := range conf.RevocationList {
   285  		crl, err := x509.ParseCRL(crlbytes)
   286  		if err != nil {
   287  			return fmt.Errorf("Could not parse RevocationList, err %s", err)
   288  		}
   289  		validator.CRL[i] = crl
   290  	}
   291  
   292  	return nil
   293  }
   294  
   295  func (validator *ecdsaValidator) finalizeSetupCAs(config *AuthConfig) error {
   296  	for _, cert := range append(append([]*x509.Certificate{}, validator.rootCerts...), validator.intermediateCerts...) {
   297  		if !isCACert(cert) {
   298  			return fmt.Errorf("CA Certificate did not have the Subject Key Identifier extension, (SN: %s)", cert.SerialNumber)
   299  		}
   300  
   301  		if err := validator.validateCAIdentity(cert); err != nil {
   302  			return fmt.Errorf("CA Certificate is not valid, (SN: %s) [%s]", cert.SerialNumber, err)
   303  		}
   304  	}
   305  
   306  	validator.certificationTreeInternalNodesMap = make(map[string]bool)
   307  	for _, cert := range append([]*x509.Certificate{}, validator.intermediateCerts...) {
   308  		chain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   309  		if err != nil {
   310  			return fmt.Errorf("Failed getting validation chain, (SN: %s)", cert.SerialNumber)
   311  		}
   312  
   313  		for i := 1; i < len(chain); i++ {
   314  			validator.certificationTreeInternalNodesMap[string(chain[i].Raw)] = true
   315  		}
   316  	}
   317  
   318  	return nil
   319  }
   320  
   321  func (validator *ecdsaValidator) sanitizeCert(cert *x509.Certificate) (*x509.Certificate, error) {
   322  	if isECDSASignedCert(cert) {
   323  		var parentCert *x509.Certificate
   324  		if cert.IsCA {
   325  			chain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   326  			if err != nil {
   327  				return nil, err
   328  			}
   329  			if len(chain) == 1 {
   330  				parentCert = cert
   331  			} else {
   332  				parentCert = chain[1]
   333  			}
   334  		} else {
   335  			chain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   336  			if err != nil {
   337  				return nil, err
   338  			}
   339  			parentCert = chain[1]
   340  		}
   341  
   342  		var err error
   343  		cert, err = sanitizeECDSASignedCert(cert, parentCert)
   344  		if err != nil {
   345  			return nil, err
   346  		}
   347  	}
   348  	return cert, nil
   349  }
   350  
   351  func (validator *ecdsaValidator) validateCAIdentity(cert *x509.Certificate) error {
   352  	if !cert.IsCA {
   353  		return errors.New("Only CA identities can be validated")
   354  	}
   355  
   356  	validationChain, err := validator.getUniqueValidationChain(cert, validator.getValidityOptsForCert(cert))
   357  	if err != nil {
   358  		return fmt.Errorf("Could not obtain certification chain, err %s", err)
   359  	}
   360  	if len(validationChain) == 1 {
   361  		return nil
   362  	}
   363  
   364  	return validator.validateCertAgainstChain(cert.SerialNumber, validationChain)
   365  }
   366  
   367  func (validator *ecdsaValidator) validateCertAgainstChain(serialNumber *big.Int, validationChain []*x509.Certificate) error {
   368  	SKI, err := getSubjectKeyIdentifierFromCert(validationChain[1])
   369  	if err != nil {
   370  		return fmt.Errorf("Could not obtain Subject Key Identifier for signer cert, err %s", err)
   371  	}
   372  
   373  	for _, crl := range validator.CRL {
   374  		aki, err := getAuthorityKeyIdentifierFromCrl(crl)
   375  		if err != nil {
   376  			return fmt.Errorf("Could not obtain Authority Key Identifier for crl, err %s", err)
   377  		}
   378  
   379  		if bytes.Equal(aki, SKI) {
   380  			for _, rc := range crl.TBSCertList.RevokedCertificates {
   381  				if rc.SerialNumber.Cmp(serialNumber) == 0 {
   382  					err = validationChain[1].CheckCRLSignature(crl)
   383  					if err != nil {
   384  						authLogger.Warn("Invalid signature over the identified CRL, error %s", err)
   385  						continue
   386  					}
   387  
   388  					return errors.New("The certificate has been revoked")
   389  				}
   390  			}
   391  		}
   392  	}
   393  
   394  	return nil
   395  }
   396  
   397  func (validator *ecdsaValidator) getValidityOptsForCert(cert *x509.Certificate) x509.VerifyOptions {
   398  	var tempOpts x509.VerifyOptions
   399  	tempOpts.Roots = validator.opts.Roots
   400  	tempOpts.DNSName = validator.opts.DNSName
   401  	tempOpts.Intermediates = validator.opts.Intermediates
   402  	tempOpts.KeyUsages = validator.opts.KeyUsages
   403  	tempOpts.CurrentTime = cert.NotBefore.Add(time.Second)
   404  
   405  	return tempOpts
   406  }
   407  
   408  func (validator *ecdsaValidator) GetCertFromSignature(signature []byte) ([]byte, error) {
   409  	certSign, err := utils.DecodeCertFromSignature(signature)
   410  	if err != nil {
   411  		authLogger.Error(fmt.Sprintf("unmashal certificate from signature failed. %s", err.Error()))
   412  		return nil, err
   413  	}
   414  
   415  	if len(certSign.Cert) == 0 {
   416  		authLogger.Error("cert can not be null")
   417  		return nil, types.ErrInvalidParam
   418  	}
   419  
   420  	return certSign.Cert, nil
   421  }