github.com/mangodowner/go-gm@v0.0.0-20180818020936-8baa2bd4408c/src/crypto/sm2/pkcs8.go (about)

     1  /*
     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
     6  
     7  	http://www.apache.org/licenses/LICENSE-2.0
     8  
     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.
    14  */
    15  
    16  package sm2
    17  
    18  import (
    19  	"crypto/aes"
    20  	"crypto/cipher"
    21  	"crypto/elliptic"
    22  	"crypto/hmac"
    23  	"crypto/md5"
    24  	"crypto/rand"
    25  	"crypto/sha1"
    26  	"crypto/sha256"
    27  	"crypto/sha512"
    28  	"crypto/x509/pkix"
    29  	"encoding/asn1"
    30  	"encoding/pem"
    31  	"errors"
    32  	"hash"
    33  	"io/ioutil"
    34  	"math/big"
    35  	"os"
    36  	"reflect"
    37  )
    38  
    39  /*
    40   * reference to RFC5959 and RFC2898
    41   */
    42  
    43  var (
    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
    47  
    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}
    52  
    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}
    55  
    56  	oidSM2 = asn1.ObjectIdentifier{1, 2, 840, 10045, 2, 1}
    57  )
    58  
    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
    63  	PrivateKey          []byte
    64  }
    65  
    66  // reference to https://www.rfc-editor.org/rfc/rfc5958.txt
    67  type EncryptedPrivateKeyInfo struct {
    68  	EncryptionAlgorithm Pbes2Algorithms
    69  	EncryptedData       []byte
    70  }
    71  
    72  // reference to https://www.ietf.org/rfc/rfc2898.txt
    73  type Pbes2Algorithms struct {
    74  	IdPBES2     asn1.ObjectIdentifier
    75  	Pbes2Params Pbes2Params
    76  }
    77  
    78  // reference to https://www.ietf.org/rfc/rfc2898.txt
    79  type Pbes2Params struct {
    80  	KeyDerivationFunc Pbes2KDfs // PBES2-KDFs
    81  	EncryptionScheme  Pbes2Encs // PBES2-Encs
    82  }
    83  
    84  // reference to https://www.ietf.org/rfc/rfc2898.txt
    85  type Pbes2KDfs struct {
    86  	IdPBKDF2    asn1.ObjectIdentifier
    87  	Pkdf2Params Pkdf2Params
    88  }
    89  
    90  type Pbes2Encs struct {
    91  	EncryAlgo asn1.ObjectIdentifier
    92  	IV        []byte
    93  }
    94  
    95  // reference to https://www.ietf.org/rfc/rfc2898.txt
    96  type Pkdf2Params struct {
    97  	Salt           []byte
    98  	IterationCount int
    99  	Prf            pkix.AlgorithmIdentifier
   100  }
   101  
   102  type sm2PrivateKey struct {
   103  	Version       int
   104  	PrivateKey    []byte
   105  	NamedCurveOID asn1.ObjectIdentifier `asn1:"optional,explicit,tag:0"`
   106  	PublicKey     asn1.BitString        `asn1:"optional,explicit,tag:1"`
   107  }
   108  
   109  type pkcs8 struct {
   110  	Version    int
   111  	Algo       pkix.AlgorithmIdentifier
   112  	PrivateKey []byte
   113  }
   114  
   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
   120  
   121  	var buf [4]byte
   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))
   128  		prf.Reset()
   129  		prf.Write(salt)
   130  		buf[0] = byte(block >> 24)
   131  		buf[1] = byte(block >> 16)
   132  		buf[2] = byte(block >> 8)
   133  		buf[3] = byte(block)
   134  		prf.Write(buf[:4])
   135  		dk = prf.Sum(dk)
   136  		T := dk[len(dk)-hashLen:]
   137  		copy(U, T)
   138  
   139  		// U_n = PRF(password, U_(n-1))
   140  		for n := 2; n <= iter; n++ {
   141  			prf.Reset()
   142  			prf.Write(U)
   143  			U = U[:0]
   144  			U = prf.Sum(U)
   145  			for x := range U {
   146  				T[x] ^= U[x]
   147  			}
   148  		}
   149  	}
   150  	return dk[:keyLen]
   151  }
   152  
   153  func ParseSm2PublicKey(der []byte) (*PublicKey, error) {
   154  	var pubkey pkixPublicKey
   155  
   156  	if _, err := asn1.Unmarshal(der, &pubkey); err != nil {
   157  		return nil, err
   158  	}
   159  	if !reflect.DeepEqual(pubkey.Algo.Algorithm, oidSM2) {
   160  		return nil, errors.New("x509: not sm2 elliptic curve")
   161  	}
   162  	curve := P256Sm2()
   163  	x, y := elliptic.Unmarshal(curve, pubkey.BitString.Bytes)
   164  	pub := PublicKey{
   165  		Curve: curve,
   166  		X:     x,
   167  		Y:     y,
   168  	}
   169  	return &pub, nil
   170  }
   171  
   172  func MarshalSm2PublicKey(key *PublicKey) ([]byte, error) {
   173  	var r pkixPublicKey
   174  	var algo pkix.AlgorithmIdentifier
   175  
   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})
   181  	r.Algo = algo
   182  	r.BitString = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
   183  	return asn1.Marshal(r)
   184  }
   185  
   186  func ParseSm2PrivateKey(der []byte) (*PrivateKey, error) {
   187  	var privKey sm2PrivateKey
   188  
   189  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
   190  		return nil, errors.New("x509: failed to parse SM2 private key: " + err.Error())
   191  	}
   192  	curve := P256Sm2()
   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")
   197  	}
   198  	priv := new(PrivateKey)
   199  	priv.Curve = curve
   200  	priv.D = k
   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")
   205  		}
   206  		privKey.PrivateKey = privKey.PrivateKey[1:]
   207  	}
   208  	copy(privateKey[len(privateKey)-len(privKey.PrivateKey):], privKey.PrivateKey)
   209  	priv.X, priv.Y = curve.ScalarBaseMult(privateKey)
   210  	return priv, nil
   211  }
   212  
   213  func ParsePKCS8UnecryptedPrivateKey(der []byte) (*PrivateKey, error) {
   214  	var privKey pkcs8
   215  
   216  	if _, err := asn1.Unmarshal(der, &privKey); err != nil {
   217  		return nil, err
   218  	}
   219  	if !reflect.DeepEqual(privKey.Algo.Algorithm, oidSM2) {
   220  		return nil, errors.New("x509: not sm2 elliptic curve")
   221  	}
   222  	return ParseSm2PrivateKey(privKey.PrivateKey)
   223  }
   224  
   225  func ParsePKCS8EcryptedPrivateKey(der, pwd []byte) (*PrivateKey, error) {
   226  	var keyInfo EncryptedPrivateKeyInfo
   227  
   228  	_, err := asn1.Unmarshal(der, &keyInfo)
   229  	if err != nil {
   230  		return nil, errors.New("x509: unknown format")
   231  	}
   232  	if !reflect.DeepEqual(keyInfo.EncryptionAlgorithm.IdPBES2, oidPBES2) {
   233  		return nil, errors.New("x509: only support PBES2")
   234  	}
   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")
   239  	}
   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")
   244  	}
   245  	iv := encryptionScheme.IV
   246  	salt := pkdf2Params.Salt
   247  	iter := pkdf2Params.IterationCount
   248  	encryptedKey := keyInfo.EncryptedData
   249  	var key []byte
   250  	switch {
   251  	case pkdf2Params.Prf.Algorithm.Equal(oidKEYMD5):
   252  		key = pbkdf(pwd, salt, iter, 32, md5.New)
   253  		break
   254  	case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA1):
   255  		key = pbkdf(pwd, salt, iter, 32, sha1.New)
   256  		break
   257  	case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA256):
   258  		key = pbkdf(pwd, salt, iter, 32, sha256.New)
   259  		break
   260  	case pkdf2Params.Prf.Algorithm.Equal(oidKEYSHA512):
   261  		key = pbkdf(pwd, salt, iter, 32, sha512.New)
   262  		break
   263  	default:
   264  		return nil, errors.New("x509: unknown hash algorithm")
   265  	}
   266  	block, err := aes.NewCipher(key)
   267  	if err != nil {
   268  		return nil, err
   269  	}
   270  	mode := cipher.NewCBCDecrypter(block, iv)
   271  	mode.CryptBlocks(encryptedKey, encryptedKey)
   272  	rKey, err := ParsePKCS8UnecryptedPrivateKey(encryptedKey)
   273  	if err != nil {
   274  		return nil, errors.New("pkcs8: incorrect password")
   275  	}
   276  	return rKey, nil
   277  }
   278  
   279  func ParsePKCS8PrivateKey(der, pwd []byte) (*PrivateKey, error) {
   280  	if pwd == nil {
   281  		return ParsePKCS8UnecryptedPrivateKey(der)
   282  	}
   283  	return ParsePKCS8EcryptedPrivateKey(der, pwd)
   284  }
   285  
   286  func MarshalSm2UnecryptedPrivateKey(key *PrivateKey) ([]byte, error) {
   287  	var r pkcs8
   288  	var priv sm2PrivateKey
   289  	var algo pkix.AlgorithmIdentifier
   290  
   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})
   296  	priv.Version = 1
   297  	priv.NamedCurveOID = oidNamedCurveP256SM2
   298  	priv.PublicKey = asn1.BitString{Bytes: elliptic.Marshal(key.Curve, key.X, key.Y)}
   299  	priv.PrivateKey = key.D.Bytes()
   300  	r.Version = 0
   301  	r.Algo = algo
   302  	r.PrivateKey, _ = asn1.Marshal(priv)
   303  	return asn1.Marshal(r)
   304  }
   305  
   306  func MarshalSm2EcryptedPrivateKey(PrivKey *PrivateKey, pwd []byte) ([]byte, error) {
   307  	der, err := MarshalSm2UnecryptedPrivateKey(PrivKey)
   308  	if err != nil {
   309  		return nil, err
   310  	}
   311  	iter := 2048
   312  	salt := make([]byte, 8)
   313  	iv := make([]byte, 16)
   314  	rand.Reader.Read(salt)
   315  	rand.Reader.Read(iv)
   316  	key := pbkdf(pwd, salt, iter, 32, sha1.New) // 默认是SHA1
   317  	padding := aes.BlockSize - len(der)%aes.BlockSize
   318  	if padding > 0 {
   319  		n := len(der)
   320  		der = append(der, make([]byte, padding)...)
   321  		for i := 0; i < padding; i++ {
   322  			der[n+i] = byte(padding)
   323  		}
   324  	}
   325  	encryptedKey := make([]byte, len(der))
   326  	block, err := aes.NewCipher(key)
   327  	if err != nil {
   328  		return nil, err
   329  	}
   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{
   338  		oidPBKDF2,
   339  		Pkdf2Params{
   340  			salt,
   341  			iter,
   342  			algorithmIdentifier,
   343  		},
   344  	}
   345  	encryptionScheme := Pbes2Encs{
   346  		oidAES256CBC,
   347  		iv,
   348  	}
   349  	pbes2Algorithms := Pbes2Algorithms{
   350  		oidPBES2,
   351  		Pbes2Params{
   352  			keyDerivationFunc,
   353  			encryptionScheme,
   354  		},
   355  	}
   356  	encryptedPkey := EncryptedPrivateKeyInfo{
   357  		pbes2Algorithms,
   358  		encryptedKey,
   359  	}
   360  	return asn1.Marshal(encryptedPkey)
   361  }
   362  
   363  func MarshalSm2PrivateKey(key *PrivateKey, pwd []byte) ([]byte, error) {
   364  	if pwd == nil {
   365  		return MarshalSm2UnecryptedPrivateKey(key)
   366  	}
   367  	return MarshalSm2EcryptedPrivateKey(key, pwd)
   368  }
   369  
   370  func ReadPrivateKeyFromMem(data []byte, pwd []byte) (*PrivateKey, error) {
   371  	var block *pem.Block
   372  
   373  	block, _ = pem.Decode(data)
   374  	if block == nil {
   375  		return nil, errors.New("failed to decode private key")
   376  	}
   377  	priv, err := ParsePKCS8PrivateKey(block.Bytes, pwd)
   378  	return priv, err
   379  }
   380  
   381  func ReadPrivateKeyFromPem(FileName string, pwd []byte) (*PrivateKey, error) {
   382  	data, err := ioutil.ReadFile(FileName)
   383  	if err != nil {
   384  		return nil, err
   385  	}
   386  	return ReadPrivateKeyFromMem(data, pwd)
   387  }
   388  
   389  func WritePrivateKeytoMem(key *PrivateKey, pwd []byte) ([]byte, error) {
   390  	var block *pem.Block
   391  
   392  	der, err := MarshalSm2PrivateKey(key, pwd)
   393  	if err != nil {
   394  		return nil, err
   395  	}
   396  	if pwd != nil {
   397  		block = &pem.Block{
   398  			Type:  "ENCRYPTED PRIVATE KEY",
   399  			Bytes: der,
   400  		}
   401  	} else {
   402  		block = &pem.Block{
   403  			Type:  "PRIVATE KEY",
   404  			Bytes: der,
   405  		}
   406  	}
   407  	return pem.EncodeToMemory(block), nil
   408  }
   409  
   410  func WritePrivateKeytoPem(FileName string, key *PrivateKey, pwd []byte) (bool, error) {
   411  	var block *pem.Block
   412  
   413  	der, err := MarshalSm2PrivateKey(key, pwd)
   414  	if err != nil {
   415  		return false, err
   416  	}
   417  	if pwd != nil {
   418  		block = &pem.Block{
   419  			Type:  "ENCRYPTED PRIVATE KEY",
   420  			Bytes: der,
   421  		}
   422  	} else {
   423  		block = &pem.Block{
   424  			Type:  "PRIVATE KEY",
   425  			Bytes: der,
   426  		}
   427  	}
   428  	file, err := os.Create(FileName)
   429  	if err != nil {
   430  		return false, err
   431  	}
   432  	defer file.Close()
   433  	err = pem.Encode(file, block)
   434  	if err != nil {
   435  		return false, err
   436  	}
   437  	return true, nil
   438  }
   439  
   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")
   444  	}
   445  	pub, err := ParseSm2PublicKey(block.Bytes)
   446  	return pub, err
   447  }
   448  
   449  func ReadPublicKeyFromPem(FileName string, pwd []byte) (*PublicKey, error) {
   450  	data, err := ioutil.ReadFile(FileName)
   451  	if err != nil {
   452  		return nil, err
   453  	}
   454  	return ReadPublicKeyFromMem(data, pwd)
   455  }
   456  
   457  func WritePublicKeytoMem(key *PublicKey, _ []byte) ([]byte, error) {
   458  	der, err := MarshalSm2PublicKey(key)
   459  	if err != nil {
   460  		return nil, err
   461  	}
   462  	block := &pem.Block{
   463  		Type:  "PUBLIC KEY",
   464  		Bytes: der,
   465  	}
   466  	return pem.EncodeToMemory(block), nil
   467  }
   468  
   469  func WritePublicKeytoPem(FileName string, key *PublicKey, _ []byte) (bool, error) {
   470  	der, err := MarshalSm2PublicKey(key)
   471  	if err != nil {
   472  		return false, err
   473  	}
   474  	block := &pem.Block{
   475  		Type:  "PUBLIC KEY",
   476  		Bytes: der,
   477  	}
   478  	file, err := os.Create(FileName)
   479  	defer file.Close()
   480  	if err != nil {
   481  		return false, err
   482  	}
   483  	err = pem.Encode(file, block)
   484  	if err != nil {
   485  		return false, err
   486  	}
   487  	return true, nil
   488  }