2 Copyright Suzhou Tongji Fintech Research Institute 2017 All Rights Reserved.
3 Licensed under the Apache License, Version 2.0 (the "License");
4 you may not use this file except in compliance with the License.
5 You may obtain a copy of the License at
7 http://www.apache.org/licenses/LICENSE-2.0
9 Unless required by applicable law or agreed to in writing, software
10 distributed under the License is distributed on an "AS IS" BASIS,
11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 See the License for the specific language governing permissions and
13 limitations under the License.
40 * reference to RFC5959 and RFC2898
44 oidPBES1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 3} // pbeWithMD5AndDES-CBC(PBES1)
45 oidPBES2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 13} // id-PBES2(PBES2)
46 oidPBKDF2 = asn1.ObjectIdentifier{1, 2, 840, 113549, 1, 5, 12} // id-PBKDF2
48 oidKEYMD5 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 5}
49 oidKEYSHA1 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 7}
50 oidKEYSHA256 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 9}
51 oidKEYSHA512 = asn1.ObjectIdentifier{1, 2, 840, 113549, 2, 11}
53 oidAES128CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 2}
54 oidAES256CBC = asn1.ObjectIdentifier{2, 16, 840, 1, 101, 3, 4, 1, 42}
56 oidSM2 = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
59 // reference to https://www.rfc-editor.org/rfc/rfc5958.txt
60 type PrivateKeyInfo struct {
61 Version int // v1 or v2
62 PrivateKeyAlgorithm []asn1.ObjectIdentifier
66 // reference to https://www.rfc-editor.org/rfc/rfc5958.txt
67 type EncryptedPrivateKeyInfo struct {
68 EncryptionAlgorithm Pbes2Algorithms
72 // reference to https://www.ietf.org/rfc/rfc2898.txt
73 type Pbes2Algorithms struct {
74 IdPBES2 asn1.ObjectIdentifier
75 Pbes2Params Pbes2Params
78 // reference to https://www.ietf.org/rfc/rfc2898.txt
79 type Pbes2Params struct {
80 KeyDerivationFunc Pbes2KDfs // PBES2-KDFs
81 EncryptionScheme Pbes2Encs // PBES2-Encs
84 // reference to https://www.ietf.org/rfc/rfc2898.txt
85 type Pbes2KDfs struct {
86 IdPBKDF2 asn1.ObjectIdentifier
87 Pkdf2Params Pkdf2Params
90 type Pbes2Encs struct {
91 EncryAlgo asn1.ObjectIdentifier
95 // reference to https://www.ietf.org/rfc/rfc2898.txt
96 type Pkdf2Params struct {
99 Prf pkix.AlgorithmIdentifier
102 type sm2PrivateKey struct {
105 NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
106 PublicKey asn1.BitString `asn1:"optional,explicit,tag:1"`
111 Algo pkix.AlgorithmIdentifier
115 // copy from crypto/pbkdf2.go
116 func pbkdf(password, salt []byte, iter, keyLen int, h func() hash.Hash) []byte {
117 prf := hmac.New(h, password)
118 hashLen := prf.Size()
119 numBlocks := (keyLen + hashLen - 1) / hashLen
122 dk := make([]byte, 0, numBlocks*hashLen)
123 U := make([]byte, hashLen)
124 for block := 1; block <= numBlocks; block++ {
125 // N.B.: || means concatenation, ^ means XOR
126 // for each block T_i = U_1 ^ U_2 ^ ... ^ U_iter
127 // U_1 = PRF(password, salt || uint(i))
130 buf[0] = byte(block >> 24)
131 buf[1] = byte(block >> 16)
132 buf[2] = byte(block >> 8)
136 T := dk[len(dk)-hashLen:]
139 // U_n = PRF(password, U_(n-1))
140 for n := 2; n <= iter; n++ {
153 func ParseSm2PublicKey(der []byte) (*PublicKey, error) {
154 var pubkey pkixPublicKey
156 if _, err := asn1.Unmarshal(der, &pubkey); err != nil {
159 if !reflect.DeepEqual(pubkey.Algo.Algorithm, oidSM2) {
160 return nil, errors.New("x509: not sm2 elliptic curve")
163 x, y := elliptic.Unmarshal(curve, pubkey.BitString.Bytes)
172 func MarshalSm2PublicKey(key *PublicKey) ([]byte, error) {
174 var algo pkix.AlgorithmIdentifier
176 algo.Algorithm = oidSM2
177 algo.Parameters.Class = 0
178 algo.Parameters.Tag = 6
179 algo.Parameters.IsCompound = false
180 algo.Parameters.FullBytes = []byte{6, 8, 42, 129, 28, 207, 85, 1, 130, 45} // asn1.Marshal(asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301})
182 r.BitString = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
183 return asn1.Marshal(r)
186 func ParseSm2PrivateKey(der []byte) (*PrivateKey, error) {
187 var privKey sm2PrivateKey
189 if _, err := asn1.Unmarshal(der, &privKey); err != nil {
190 return nil, errors.New("x509: failed to parse SM2 private key: " + err.Error())
193 k := new(big.Int).SetBytes(privKey.PrivateKey)
194 curveOrder := curve.Params().N
195 if k.Cmp(curveOrder) >= 0 {
196 return nil, errors.New("x509: invalid elliptic curve private key value")
198 priv := new(PrivateKey)
201 privateKey := make([]byte, (curveOrder.BitLen()+7)/8)
202 for len(privKey.PrivateKey) > len(privateKey) {
203 if privKey.PrivateKey[0] != 0 {
204 return nil, errors.New("x509: invalid private key length")
206 privKey.PrivateKey = privKey.PrivateKey[1:]
208 copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
209 priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
213 func ParsePKCS8UnecryptedPrivateKey(der []byte) (*PrivateKey, error) {
216 if _, err := asn1.Unmarshal(der, &privKey); err != nil {
219 if !reflect.DeepEqual(privKey.Algo.Algorithm, oidSM2) {
220 return nil, errors.New("x509: not sm2 elliptic curve")
222 return ParseSm2PrivateKey(privKey.PrivateKey)
225 func ParsePKCS8EcryptedPrivateKey(der, pwd []byte) (*PrivateKey, error) {
226 var keyInfo EncryptedPrivateKeyInfo
228 _, err := asn1.Unmarshal(der, &keyInfo)
230 return nil, errors.New("x509: unknown format")
232 if !reflect.DeepEqual(keyInfo.EncryptionAlgorithm.IdPBES2, oidPBES2) {
233 return nil, errors.New("x509: only support PBES2")
235 encryptionScheme := keyInfo.EncryptionAlgorithm.Pbes2Params.EncryptionScheme
236 keyDerivationFunc := keyInfo.EncryptionAlgorithm.Pbes2Params.KeyDerivationFunc
237 if !reflect.DeepEqual(keyDerivationFunc.IdPBKDF2, oidPBKDF2) {
238 return nil, errors.New("x509: only support PBKDF2")
240 pkdf2Params := keyDerivationFunc.Pkdf2Params
241 if !reflect.DeepEqual(encryptionScheme.EncryAlgo, oidAES128CBC) &&
242 !reflect.DeepEqual(encryptionScheme.EncryAlgo, oidAES256CBC) {
243 return nil, errors.New("x509: unknow encryption algorithm")
245 iv := encryptionScheme.IV
246 salt := pkdf2Params.Salt
247 iter := pkdf2Params.IterationCount
248 encryptedKey := keyInfo.EncryptedData
251 case pkdf2Params.Prf.Algorithm.Equal(oidKEYMD5):
252 key = pbkdf(pwd, salt, iter, 32, md5.New)
254 case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA1):
255 key = pbkdf(pwd, salt, iter, 32, sha1.New)
257 case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA256):
258 key = pbkdf(pwd, salt, iter, 32, sha256.New)
260 case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA512):
261 key = pbkdf(pwd, salt, iter, 32, sha512.New)
264 return nil, errors.New("x509: unknown hash algorithm")
266 block, err := aes.NewCipher(key)
270 mode := cipher.NewCBCDecrypter(block, iv)
271 mode.CryptBlocks(encryptedKey, encryptedKey)
272 rKey, err := ParsePKCS8UnecryptedPrivateKey(encryptedKey)
274 return nil, errors.New("pkcs8: incorrect password")
279 func ParsePKCS8PrivateKey(der, pwd []byte) (*PrivateKey, error) {
281 return ParsePKCS8UnecryptedPrivateKey(der)
283 return ParsePKCS8EcryptedPrivateKey(der, pwd)
286 func MarshalSm2UnecryptedPrivateKey(key *PrivateKey) ([]byte, error) {
288 var priv sm2PrivateKey
289 var algo pkix.AlgorithmIdentifier
291 algo.Algorithm = oidSM2
292 algo.Parameters.Class = 0
293 algo.Parameters.Tag = 6
294 algo.Parameters.IsCompound = false
295 algo.Parameters.FullBytes = []byte{6, 8, 42, 129, 28, 207, 85, 1, 130, 45} // asn1.Marshal(asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 301})
297 priv.NamedCurveOID = oidNamedCurveP256SM2
298 priv.PublicKey = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
299 priv.PrivateKey = key.D.Bytes()
302 r.PrivateKey, _ = asn1.Marshal(priv)
303 return asn1.Marshal(r)
306 func MarshalSm2EcryptedPrivateKey(PrivKey *PrivateKey, pwd []byte) ([]byte, error) {
307 der, err := MarshalSm2UnecryptedPrivateKey(PrivKey)
312 salt := make([]byte, 8)
313 iv := make([]byte, 16)
314 rand.Reader.Read(salt)
316 key := pbkdf(pwd, salt, iter, 32, sha1.New) // 默认是SHA1
317 padding := aes.BlockSize - len(der)%aes.BlockSize
320 der = append(der, make([]byte, padding)...)
321 for i := 0; i < padding; i++ {
322 der[n+i] = byte(padding)
325 encryptedKey := make([]byte, len(der))
326 block, err := aes.NewCipher(key)
330 mode := cipher.NewCBCEncrypter(block, iv)
331 mode.CryptBlocks(encryptedKey, der)
332 var algorithmIdentifier pkix.AlgorithmIdentifier
333 algorithmIdentifier.Algorithm = oidKEYSHA1
334 algorithmIdentifier.Parameters.Tag = 5
335 algorithmIdentifier.Parameters.IsCompound = false
336 algorithmIdentifier.Parameters.FullBytes = []byte{5, 0}
337 keyDerivationFunc := Pbes2KDfs{
345 encryptionScheme := Pbes2Encs{
349 pbes2Algorithms := Pbes2Algorithms{
356 encryptedPkey := EncryptedPrivateKeyInfo{
360 return asn1.Marshal(encryptedPkey)
363 func MarshalSm2PrivateKey(key *PrivateKey, pwd []byte) ([]byte, error) {
365 return MarshalSm2UnecryptedPrivateKey(key)
367 return MarshalSm2EcryptedPrivateKey(key, pwd)
370 func ReadPrivateKeyFromMem(data []byte, pwd []byte) (*PrivateKey, error) {
373 block, _ = pem.Decode(data)
375 return nil, errors.New("failed to decode private key")
377 priv, err := ParsePKCS8PrivateKey(block.Bytes, pwd)
381 func ReadPrivateKeyFromPem(FileName string, pwd []byte) (*PrivateKey, error) {
382 data, err := ioutil.ReadFile(FileName)
386 return ReadPrivateKeyFromMem(data, pwd)
389 func WritePrivateKeytoMem(key *PrivateKey, pwd []byte) ([]byte, error) {
392 der, err := MarshalSm2PrivateKey(key, pwd)
398 Type: "ENCRYPTED PRIVATE KEY",
407 return pem.EncodeToMemory(block), nil
410 func WritePrivateKeytoPem(FileName string, key *PrivateKey, pwd []byte) (bool, error) {
413 der, err := MarshalSm2PrivateKey(key, pwd)
419 Type: "ENCRYPTED PRIVATE KEY",
428 file, err := os.Create(FileName)
433 err = pem.Encode(file, block)
440 func ReadPublicKeyFromMem(data []byte, _ []byte) (*PublicKey, error) {
441 block, _ := pem.Decode(data)
442 if block == nil || block.Type != "PUBLIC KEY" {
443 return nil, errors.New("failed to decode public key")
445 pub, err := ParseSm2PublicKey(block.Bytes)
449 func ReadPublicKeyFromPem(FileName string, pwd []byte) (*PublicKey, error) {
450 data, err := ioutil.ReadFile(FileName)
454 return ReadPublicKeyFromMem(data, pwd)
457 func WritePublicKeytoMem(key *PublicKey, _ []byte) ([]byte, error) {
458 der, err := MarshalSm2PublicKey(key)
466 return pem.EncodeToMemory(block), nil
469 func WritePublicKeytoPem(FileName string, key *PublicKey, _ []byte) (bool, error) {
470 der, err := MarshalSm2PublicKey(key)
478 file, err := os.Create(FileName)
483 err = pem.Encode(file, block)