gitee.com/lh-her-team/common@v1.5.1/crypto/asym/sm2/pkcs8.go (about) 1 // Copyright 2015 The Go Authors. 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 sm2 6 7 import ( 8 "crypto/ecdsa" 9 "crypto/elliptic" 10 "crypto/rsa" 11 "crypto/x509" 12 "crypto/x509/pkix" 13 "encoding/asn1" 14 "errors" 15 "fmt" 16 "math/big" 17 18 tjsm2 "github.com/tjfoc/gmsm/sm2" 19 ) 20 21 type pkcs8 struct { // Duplicated from x509 package 22 Version int 23 Algo pkix.AlgorithmIdentifier 24 PrivateKey []byte 25 } 26 27 var ( // Duplicated from x509 package 28 oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1} 29 oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1} 30 ) 31 32 var ( // Duplicated from x509 package 33 oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33} 34 oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7} 35 oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34} 36 oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35} 37 // I get the SM2 ID through parsing the pem file generated by gmssl 38 oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301} 39 ) 40 41 func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) { // Duplicated from x509 package 42 switch curve { 43 case elliptic.P224(): 44 return oidNamedCurveP224, true 45 case elliptic.P256(): 46 return oidNamedCurveP256, true 47 case elliptic.P384(): 48 return oidNamedCurveP384, true 49 case elliptic.P521(): 50 return oidNamedCurveP521, true 51 case tjsm2.P256Sm2(): 52 return oidNamedCurveP256SM2, true 53 } 54 return nil, false 55 } 56 57 func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve { 58 switch { 59 case oid.Equal(oidNamedCurveP224): 60 return elliptic.P224() 61 case oid.Equal(oidNamedCurveP256): 62 return elliptic.P256() 63 case oid.Equal(oidNamedCurveP384): 64 return elliptic.P384() 65 case oid.Equal(oidNamedCurveP521): 66 return elliptic.P521() 67 case oid.Equal(oidNamedCurveP256SM2): 68 return tjsm2.P256Sm2() 69 } 70 return nil 71 } 72 73 func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) { 74 var privKey pkcs8 75 if _, err = asn1.Unmarshal(der, &privKey); err != nil { 76 return nil, err 77 } 78 switch { 79 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA): 80 bytes := privKey.Algo.Parameters.FullBytes 81 namedCurveOID := new(asn1.ObjectIdentifier) 82 if _, err = asn1.Unmarshal(bytes, namedCurveOID); err != nil { 83 namedCurveOID = nil 84 } 85 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey) 86 if err != nil { 87 return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error()) 88 } 89 return key, nil 90 default: 91 return nil, fmt.Errorf("x509: PKCS#8 unknown private key: %v", privKey.Algo.Algorithm) 92 } 93 } 94 95 func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) { 96 var privKey ecPrivateKey 97 if _, err := asn1.Unmarshal(der, &privKey); err != nil { 98 return nil, errors.New("x509: failed to parse EC private key: " + err.Error()) 99 } 100 if privKey.Version != 1 { 101 return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version) 102 } 103 var curve elliptic.Curve 104 if namedCurveOID != nil { 105 curve = namedCurveFromOID(*namedCurveOID) 106 } else { 107 curve = namedCurveFromOID(privKey.NamedCurveOID) 108 } 109 if curve == nil { 110 return nil, errors.New("x509: unknown elliptic curve") 111 } 112 k := new(big.Int).SetBytes(privKey.PrivateKey) 113 curveOrder := curve.Params().N 114 if k.Cmp(curveOrder) >= 0 { 115 return nil, errors.New("x509: invalid elliptic curve private key value") 116 } 117 priv := new(ecdsa.PrivateKey) 118 priv.Curve = curve 119 priv.D = k 120 privateKey := make([]byte, (curveOrder.BitLen()+7)/8) 121 // Some private keys have leading zero padding. This is invalid 122 // according to [SEC1], but this code will ignore it. 123 for len(privKey.PrivateKey) > len(privateKey) { 124 if privKey.PrivateKey[0] != 0 { 125 return nil, errors.New("x509: invalid private key length") 126 } 127 privKey.PrivateKey = privKey.PrivateKey[1:] 128 } 129 // Some private keys remove all leading zeros, this is also invalid 130 // according to [SEC1] but since OpenSSL used to do this, we ignore 131 // this too. 132 copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey) 133 priv.X, priv.Y = curve.ScalarBaseMult(privateKey) 134 return priv, nil 135 } 136 137 func MarshalPKCS8PrivateKey(key interface{}) (der []byte, err error) { 138 var privKey pkcs8 139 switch key := key.(type) { 140 case *rsa.PrivateKey: 141 privKey.Algo.Algorithm = oidPublicKeyRSA 142 // This is a NULL parameters value which is technically 143 // superfluous, but most other code includes it. 144 privKey.Algo.Parameters = asn1.RawValue{ 145 Tag: 5, 146 } 147 privKey.PrivateKey = x509.MarshalPKCS1PrivateKey(key) 148 case *ecdsa.PrivateKey: 149 privKey.Algo.Algorithm = oidPublicKeyECDSA 150 namedCurveOID, ok := oidFromNamedCurve(key.Curve) 151 if !ok { 152 return nil, errors.New("go-pkcs12: unknown elliptic curve") 153 } 154 if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil { 155 return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error()) 156 } 157 if privKey.PrivateKey, err = x509.MarshalECPrivateKey(key); err != nil { 158 return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error()) 159 } 160 case *tjsm2.PrivateKey: 161 privKey.Algo.Algorithm = oidPublicKeyECDSA 162 namedCurveOID, ok := oidFromNamedCurve(key.Curve) 163 if !ok { 164 return nil, errors.New("go-pkcs12: unknown elliptic curve") 165 } 166 if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil { 167 return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error()) 168 } 169 if privKey.PrivateKey, err = MarshalECPrivateKey(key); err != nil { 170 return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error()) 171 } 172 default: 173 return nil, errors.New("go-pkcs12: only RSA and ECDSA private keys supported") 174 } 175 return asn1.Marshal(privKey) 176 } 177 178 func MarshalECPrivateKey(key *tjsm2.PrivateKey) ([]byte, error) { 179 oid, ok := oidFromNamedCurve(key.Curve) 180 if !ok { 181 return nil, errors.New("x509: unknown elliptic curve") 182 } 183 return MarshalPrivateKey(key, oid) 184 } 185 186 func MarshalPrivateKey(key *tjsm2.PrivateKey, oid asn1.ObjectIdentifier) ([]byte, error) { 187 privateKeyBytes := key.D.Bytes() 188 paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8) 189 copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes) 190 return asn1.Marshal(ecPrivateKey{ 191 Version: 1, 192 PrivateKey: paddedPrivateKey, 193 NamedCurveOID: oid, 194 PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}, 195 }) 196 } 197 198 type ecPrivateKey struct { 199 Version int 200 PrivateKey []byte 201 NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"` 202 PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"` 203 }