github.com/Hyperledger-TWGC/tjfoc-gm@v1.4.0/x509/utils.go (about)

     1  package x509
     2  
     3  import (
     4  	"bytes"
     5  	"crypto"
     6  	"crypto/rand"
     7  	"crypto/rsa"
     8  	"crypto/x509"
     9  	"encoding/asn1"
    10  	"encoding/pem"
    11  	"errors"
    12  	"github.com/Hyperledger-TWGC/tjfoc-gm/sm2"
    13  )
    14  
    15  func ReadPrivateKeyFromPem(privateKeyPem []byte, pwd []byte) (*sm2.PrivateKey, error) {
    16  	var block *pem.Block
    17  	block, _ = pem.Decode(privateKeyPem)
    18  	if block == nil {
    19  		return nil, errors.New("failed to decode private key")
    20  	}
    21  	priv, err := ParsePKCS8PrivateKey(block.Bytes, pwd)
    22  	return priv, err
    23  }
    24  
    25  func WritePrivateKeyToPem(key *sm2.PrivateKey, pwd []byte) ([]byte, error) {
    26  	var block *pem.Block
    27  	der, err := MarshalSm2PrivateKey(key, pwd) //Convert private key to DER format
    28  	if err != nil {
    29  		return nil, err
    30  	}
    31  	if pwd != nil {
    32  		block = &pem.Block{
    33  			Type:  "ENCRYPTED PRIVATE KEY",
    34  			Bytes: der,
    35  		}
    36  	} else {
    37  		block = &pem.Block{
    38  			Type:  "PRIVATE KEY",
    39  			Bytes: der,
    40  		}
    41  	}
    42  	certPem := pem.EncodeToMemory(block)
    43  	return certPem, nil
    44  }
    45  
    46  func ReadPublicKeyFromPem(publicKeyPem []byte) (*sm2.PublicKey, error) {
    47  	block, _ := pem.Decode(publicKeyPem)
    48  	if block == nil || block.Type != "PUBLIC KEY" {
    49  		return nil, errors.New("failed to decode public key")
    50  	}
    51  	return ParseSm2PublicKey(block.Bytes)
    52  }
    53  
    54  func WritePublicKeyToPem(key *sm2.PublicKey) ([]byte, error) {
    55  	der, err := MarshalSm2PublicKey(key) //Convert publick key to DER format
    56  	if err != nil {
    57  		return nil, err
    58  	}
    59  	block := &pem.Block{
    60  		Type:  "PUBLIC KEY",
    61  		Bytes: der,
    62  	}
    63  	certPem := pem.EncodeToMemory(block)
    64  	return certPem, nil
    65  }
    66  
    67  func ReadCertificateRequestFromPem(certPem []byte) (*CertificateRequest, error) {
    68  	block, _ := pem.Decode(certPem)
    69  	if block == nil {
    70  		return nil, errors.New("failed to decode certificate request")
    71  	}
    72  	return ParseCertificateRequest(block.Bytes)
    73  }
    74  
    75  func CreateCertificateRequestToPem(template *CertificateRequest, signer crypto.Signer) ([]byte, error) {
    76  	der, err := CreateCertificateRequest(rand.Reader, template, signer)
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  	block := &pem.Block{
    81  		Type:  "CERTIFICATE REQUEST",
    82  		Bytes: der,
    83  	}
    84  	certPem := pem.EncodeToMemory(block)
    85  	return certPem, nil
    86  }
    87  
    88  func ReadCertificateFromPem(certPem []byte) (*Certificate, error) {
    89  	block, _ := pem.Decode(certPem)
    90  	if block == nil {
    91  		return nil, errors.New("failed to decode certificate request")
    92  	}
    93  	return ParseCertificate(block.Bytes)
    94  }
    95  
    96  // CreateCertificate creates a new certificate based on a template. The
    97  // following members of template are used: SerialNumber, Subject, NotBefore,
    98  // NotAfter, KeyUsage, ExtKeyUsage, UnknownExtKeyUsage, BasicConstraintsValid,
    99  // IsCA, MaxPathLen, SubjectKeyId, DNSNames, PermittedDNSDomainsCritical,
   100  // PermittedDNSDomains, SignatureAlgorithm.
   101  //
   102  // The certificate is signed by parent. If parent is equal to template then the
   103  // certificate is self-signed. The parameter pub is the public key of the
   104  // signee and priv is the private key of the signer.
   105  //
   106  // The returned slice is the certificate in DER encoding.
   107  //
   108  // All keys types that are implemented via crypto.Signer are supported (This
   109  // includes *rsa.PublicKey and *ecdsa.PublicKey.)
   110  func CreateCertificate(template, parent *Certificate, publicKey *sm2.PublicKey, signer crypto.Signer) ([]byte, error) {
   111  	if template.SerialNumber == nil {
   112  		return nil, errors.New("x509: no SerialNumber given")
   113  	}
   114  
   115  	hashFunc, signatureAlgorithm, err := signingParamsForPublicKey(signer.Public(), template.SignatureAlgorithm)
   116  	if err != nil {
   117  		return nil, err
   118  	}
   119  
   120  	publicKeyBytes, publicKeyAlgorithm, err := marshalPublicKey(publicKey)
   121  	if err != nil {
   122  		return nil, err
   123  	}
   124  
   125  	asn1Issuer, err := subjectBytes(parent)
   126  	if err != nil {
   127  		return nil, err
   128  	}
   129  
   130  	asn1Subject, err := subjectBytes(template)
   131  	if err != nil {
   132  		return nil, err
   133  	}
   134  
   135  	if !bytes.Equal(asn1Issuer, asn1Subject) && len(parent.SubjectKeyId) > 0 {
   136  		template.AuthorityKeyId = parent.SubjectKeyId
   137  	}
   138  
   139  	extensions, err := buildExtensions(template)
   140  	if err != nil {
   141  		return nil, err
   142  	}
   143  	encodedPublicKey := asn1.BitString{BitLength: len(publicKeyBytes) * 8, Bytes: publicKeyBytes}
   144  	c := tbsCertificate{
   145  		Version:            2,
   146  		SerialNumber:       template.SerialNumber,
   147  		SignatureAlgorithm: signatureAlgorithm,
   148  		Issuer:             asn1.RawValue{FullBytes: asn1Issuer},
   149  		Validity:           validity{template.NotBefore.UTC(), template.NotAfter.UTC()},
   150  		Subject:            asn1.RawValue{FullBytes: asn1Subject},
   151  		PublicKey:          publicKeyInfo{nil, publicKeyAlgorithm, encodedPublicKey},
   152  		Extensions:         extensions,
   153  	}
   154  
   155  	tbsCertContents, err := asn1.Marshal(c)
   156  	if err != nil {
   157  		return nil, err
   158  	}
   159  
   160  	c.Raw = tbsCertContents
   161  
   162  	digest := tbsCertContents
   163  	switch template.SignatureAlgorithm {
   164  	case SM2WithSM3, SM2WithSHA1, SM2WithSHA256:
   165  		break
   166  	default:
   167  		h := hashFunc.New()
   168  		h.Write(tbsCertContents)
   169  		digest = h.Sum(nil)
   170  	}
   171  
   172  	var signerOpts crypto.SignerOpts
   173  	signerOpts = hashFunc
   174  	if template.SignatureAlgorithm != 0 && template.SignatureAlgorithm.isRSAPSS() {
   175  		signerOpts = &rsa.PSSOptions{
   176  			SaltLength: rsa.PSSSaltLengthEqualsHash,
   177  			Hash:       crypto.Hash(hashFunc),
   178  		}
   179  	}
   180  
   181  	var signature []byte
   182  	signature, err = signer.Sign(rand.Reader, digest, signerOpts)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  	return asn1.Marshal(certificate{
   187  		nil,
   188  		c,
   189  		signatureAlgorithm,
   190  		asn1.BitString{Bytes: signature, BitLength: len(signature) * 8},
   191  	})
   192  }
   193  
   194  // CreateCertificateToPem creates a new certificate based on a template and
   195  // encodes it to PEM format. It uses CreateCertificate to create certificate
   196  // and returns its PEM format.
   197  func CreateCertificateToPem(template, parent *Certificate, pubKey *sm2.PublicKey, signer crypto.Signer) ([]byte, error) {
   198  	der, err := CreateCertificate(template, parent, pubKey, signer)
   199  	if err != nil {
   200  		return nil, err
   201  	}
   202  	block := &pem.Block{
   203  		Type:  "CERTIFICATE",
   204  		Bytes: der,
   205  	}
   206  	certPem := pem.EncodeToMemory(block)
   207  	return certPem, nil
   208  }
   209  
   210  func ParseSm2CertifateToX509(asn1data []byte) (*x509.Certificate, error) {
   211  	sm2Cert, err := ParseCertificate(asn1data)
   212  	if err != nil {
   213  		return nil, err
   214  	}
   215  	return sm2Cert.ToX509Certificate(), nil
   216  }