1
2
3
4
5 package pkcs12
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 "github.com/tjfoc/gmsm/sm2"
16 "fmt"
17 "math/big"
18 )
19
20 type pkcs8 struct {
21 Version int
22 Algo pkix.AlgorithmIdentifier
23 PrivateKey []byte
24 }
25
26 var (
27 oidPublicKeyRSA = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 1, 1}
28 oidPublicKeyECDSA = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
29 )
30
31 var (
32 oidNamedCurveP224 = asn1.ObjectIdentifier{1, 3, 132, 0, 33}
33 oidNamedCurveP256 = asn1.ObjectIdentifier{1, 2, 840, 10045, 3, 1, 7}
34 oidNamedCurveP384 = asn1.ObjectIdentifier{1, 3, 132, 0, 34}
35 oidNamedCurveP521 = asn1.ObjectIdentifier{1, 3, 132, 0, 35}
36 oidNamedCurveP256SM2 = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301}
37 )
38
39 func oidFromNamedCurve(curve elliptic.Curve) (asn1.ObjectIdentifier, bool) {
40 switch curve {
41 case elliptic.P224():
42 return oidNamedCurveP224, true
43 case elliptic.P256():
44 return oidNamedCurveP256, true
45 case elliptic.P384():
46 return oidNamedCurveP384, true
47 case elliptic.P521():
48 return oidNamedCurveP521, true
49 case sm2.P256Sm2():
50 return oidNamedCurveP256SM2, true
51 }
52
53 return nil, false
54 }
55 func namedCurveFromOID(oid asn1.ObjectIdentifier) elliptic.Curve {
56 switch {
57 case oid.Equal(oidNamedCurveP224):
58 return elliptic.P224()
59 case oid.Equal(oidNamedCurveP256):
60 return elliptic.P256()
61 case oid.Equal(oidNamedCurveP384):
62 return elliptic.P384()
63 case oid.Equal(oidNamedCurveP521):
64 return elliptic.P521()
65 case oid.Equal(oidNamedCurveP256SM2):
66 return sm2.P256Sm2()
67 }
68 return nil
69 }
70 func ParsePKCS8PrivateKey(der []byte) (key interface{}, err error) {
71 var privKey pkcs8
72 if _, err := asn1.Unmarshal(der, &privKey); err != nil {
73 return nil, err
74 }
75 switch {
76 case privKey.Algo.Algorithm.Equal(oidPublicKeyECDSA):
77 bytes := privKey.Algo.Parameters.FullBytes
78 namedCurveOID := new(asn1.ObjectIdentifier)
79 if _, err := asn1.Unmarshal(bytes, namedCurveOID); err != nil {
80 namedCurveOID = nil
81 }
82 key, err = parseECPrivateKey(namedCurveOID, privKey.PrivateKey)
83 if err != nil {
84 return nil, errors.New("x509: failed to parse EC private key embedded in PKCS#8: " + err.Error())
85 }
86 return key, nil
87
88 default:
89 return nil, fmt.Errorf("x509: PKCS#8 wrapping contained private key with unknown algorithm: %v", privKey.Algo.Algorithm)
90 }
91 }
92 func parseECPrivateKey(namedCurveOID *asn1.ObjectIdentifier, der []byte) (key *ecdsa.PrivateKey, err error) {
93 var privKey ecPrivateKey
94 if _, err := asn1.Unmarshal(der, &privKey); err != nil {
95 return nil, errors.New("x509: failed to parse EC private key: " + err.Error())
96 }
97 if privKey.Version != 1 {
98 return nil, fmt.Errorf("x509: unknown EC private key version %d", privKey.Version)
99 }
100
101 var curve elliptic.Curve
102 if namedCurveOID != nil {
103 curve = namedCurveFromOID(*namedCurveOID)
104 } else {
105 curve = namedCurveFromOID(privKey.NamedCurveOID)
106 }
107 if curve == nil {
108 return nil, errors.New("x509: unknown elliptic curve")
109 }
110
111 k := new(big.Int).SetBytes(privKey.PrivateKey)
112 curveOrder := curve.Params().N
113 if k.Cmp(curveOrder) >= 0 {
114 return nil, errors.New("x509: invalid elliptic curve private key value")
115 }
116 priv := new(ecdsa.PrivateKey)
117 priv.Curve = curve
118 priv.D = k
119
120 privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
121
122
123
124 for len(privKey.PrivateKey) > len(privateKey) {
125 if privKey.PrivateKey[0] != 0 {
126 return nil, errors.New("x509: invalid private key length")
127 }
128 privKey.PrivateKey = privKey.PrivateKey[1:]
129 }
130
131
132
133
134 copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
135 priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
136
137 return priv, nil
138 }
139 func marshalPKCS8PrivateKey(key interface{}) (der []byte, err error) {
140 var privKey pkcs8
141 switch key := key.(type) {
142 case *rsa.PrivateKey:
143 privKey.Algo.Algorithm = oidPublicKeyRSA
144
145
146 privKey.Algo.Parameters = asn1.RawValue{
147 Tag: 5,
148 }
149 privKey.PrivateKey = x509.MarshalPKCS1PrivateKey(key)
150 case *ecdsa.PrivateKey:
151 privKey.Algo.Algorithm = oidPublicKeyECDSA
152 namedCurveOID, ok := oidFromNamedCurve(key.Curve)
153 if !ok {
154 return nil, errors.New("go-pkcs12: unknown elliptic curve")
155 }
156 if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
157 return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
158 }
159 if privKey.PrivateKey, err =x509.MarshalECPrivateKey(key); err != nil {
160 return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
161 }
162 case *sm2.PrivateKey:
163 privKey.Algo.Algorithm = oidPublicKeyECDSA
164 namedCurveOID, ok := oidFromNamedCurve(key.Curve)
165 if !ok {
166 return nil, errors.New("go-pkcs12: unknown elliptic curve")
167 }
168 if privKey.Algo.Parameters.FullBytes, err = asn1.Marshal(namedCurveOID); err != nil {
169 return nil, errors.New("go-pkcs12: failed to embed OID of named curve in PKCS#8: " + err.Error())
170 }
171 if privKey.PrivateKey, err = MarshalECPrivateKey(key); err != nil {
172 return nil, errors.New("go-pkcs12: failed to embed EC private key in PKCS#8: " + err.Error())
173 }
174 default:
175 return nil, errors.New("go-pkcs12: only RSA and ECDSA private keys supported")
176 }
177 return asn1.Marshal(privKey)
178 }
179 func MarshalECPrivateKey(key *sm2.PrivateKey) ([]byte, error) {
180 oid, ok := oidFromNamedCurve(key.Curve)
181 if !ok {
182 return nil, errors.New("x509: unknown elliptic curve")
183 }
184
185 return MarshalPrivateKey(key, oid)
186 }
187 func MarshalPrivateKey(key *sm2.PrivateKey, oid asn1.ObjectIdentifier)([]byte,error){
188 privateKeyBytes := key.D.Bytes()
189 paddedPrivateKey := make([]byte, (key.Curve.Params().N.BitLen()+7)/8)
190 copy(paddedPrivateKey[len(paddedPrivateKey)-len(privateKeyBytes):], privateKeyBytes)
191 return asn1.Marshal(ecPrivateKey{
192 Version: 1,
193 PrivateKey: paddedPrivateKey,
194 NamedCurveOID: oid,
195 PublicKey: asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)},
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 }
View as plain text