github.com/turingchain2020/turingchain@v1.1.21/executor/authority/core/cert.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/ecdsa"
    10  	"crypto/x509"
    11  	"crypto/x509/pkix"
    12  	"encoding/asn1"
    13  	"errors"
    14  	"math/big"
    15  	"time"
    16  
    17  	secp256r1_util "github.com/turingchain2020/turingchain/system/crypto/secp256r1"
    18  	"github.com/tjfoc/gmsm/sm2"
    19  )
    20  
    21  type validity struct {
    22  	NotBefore, NotAfter time.Time
    23  }
    24  
    25  type publicKeyInfo struct {
    26  	Raw       asn1.RawContent
    27  	Algorithm pkix.AlgorithmIdentifier
    28  	PublicKey asn1.BitString
    29  }
    30  
    31  type certificate struct {
    32  	Raw                asn1.RawContent
    33  	TBSCertificate     tbsCertificate
    34  	SignatureAlgorithm pkix.AlgorithmIdentifier
    35  	SignatureValue     asn1.BitString
    36  }
    37  
    38  type tbsCertificate struct {
    39  	Raw                asn1.RawContent
    40  	Version            int `asn1:"optional,explicit,default:0,tag:0"`
    41  	SerialNumber       *big.Int
    42  	SignatureAlgorithm pkix.AlgorithmIdentifier
    43  	Issuer             asn1.RawValue
    44  	Validity           validity
    45  	Subject            asn1.RawValue
    46  	PublicKey          publicKeyInfo
    47  	UniqueID           asn1.BitString   `asn1:"optional,tag:1"`
    48  	SubjectUniqueID    asn1.BitString   `asn1:"optional,tag:2"`
    49  	Extensions         []pkix.Extension `asn1:"optional,explicit,tag:3"`
    50  }
    51  
    52  func isECDSASignedCert(cert *x509.Certificate) bool {
    53  	return cert.SignatureAlgorithm == x509.ECDSAWithSHA1 ||
    54  		cert.SignatureAlgorithm == x509.ECDSAWithSHA256 ||
    55  		cert.SignatureAlgorithm == x509.ECDSAWithSHA384 ||
    56  		cert.SignatureAlgorithm == x509.ECDSAWithSHA512
    57  }
    58  
    59  func sanitizeECDSASignedCert(cert *x509.Certificate, parentCert *x509.Certificate) (*x509.Certificate, error) {
    60  	if cert == nil {
    61  		return nil, errors.New("Certificate must be different from nil")
    62  	}
    63  	if parentCert == nil {
    64  		return nil, errors.New("Parent certificate must be different from nil")
    65  	}
    66  
    67  	expectedSig, err := signatureToLowS(parentCert.PublicKey.(*ecdsa.PublicKey), cert.Signature)
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	if bytes.Equal(cert.Signature, expectedSig) {
    73  		return cert, nil
    74  	}
    75  
    76  	var newCert certificate
    77  	newCert, err = certFromX509Cert(cert)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  
    82  	newCert.SignatureValue = asn1.BitString{Bytes: expectedSig, BitLength: len(expectedSig) * 8}
    83  
    84  	newCert.Raw = nil
    85  	newRaw, err := asn1.Marshal(newCert)
    86  	if err != nil {
    87  		return nil, err
    88  	}
    89  
    90  	return x509.ParseCertificate(newRaw)
    91  }
    92  
    93  func signatureToLowS(k *ecdsa.PublicKey, signature []byte) ([]byte, error) {
    94  	r, s, err := secp256r1_util.UnmarshalECDSASignature(signature)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  
    99  	s = secp256r1_util.ToLowS(k, s)
   100  	return secp256r1_util.MarshalECDSASignature(r, s)
   101  }
   102  
   103  func certFromX509Cert(cert *x509.Certificate) (certificate, error) {
   104  	var newCert certificate
   105  	_, err := asn1.Unmarshal(cert.Raw, &newCert)
   106  	if err != nil {
   107  		return certificate{}, err
   108  	}
   109  	return newCert, nil
   110  }
   111  
   112  // ParseECDSAPubKey2SM2PubKey 将ECDSA的公钥转成SM2公钥
   113  func ParseECDSAPubKey2SM2PubKey(key *ecdsa.PublicKey) *sm2.PublicKey {
   114  	sm2Key := &sm2.PublicKey{
   115  		Curve: key.Curve,
   116  		X:     key.X,
   117  		Y:     key.Y,
   118  	}
   119  
   120  	return sm2Key
   121  }