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 }