mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 20:26:19 +08:00
cfca: extract encrypt/decrypt functions with SM4CBC and SM3 KDF
This commit is contained in:
parent
65532624e8
commit
6a98350f2e
57
cfca/encrypt.go
Normal file
57
cfca/encrypt.go
Normal file
@ -0,0 +1,57 @@
|
||||
// Copyright 2024 Sun Yimin. All rights reserved.
|
||||
// Use of this source code is governed by a MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package cfca
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"errors"
|
||||
|
||||
"github.com/emmansun/gmsm/padding"
|
||||
"github.com/emmansun/gmsm/sm3"
|
||||
"github.com/emmansun/gmsm/sm4"
|
||||
)
|
||||
|
||||
// NewSM4CBCBlockMode creates a new SM4-CBC block mode with the password.
|
||||
func NewSM4CBCBlockMode(password []byte, isEncrypter bool) (cipher.BlockMode, error) {
|
||||
if len(password) == 0 {
|
||||
return nil, errors.New("cfca: invalid password")
|
||||
}
|
||||
ivkey := sm3.Kdf(password, 32)
|
||||
block, err := sm4.NewCipher(ivkey[16:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isEncrypter {
|
||||
return cipher.NewCBCEncrypter(block, ivkey[:16]), nil
|
||||
}
|
||||
return cipher.NewCBCDecrypter(block, ivkey[:16]), nil
|
||||
}
|
||||
|
||||
// EncryptBySM4CBC encrypts the data with the password using SM4-CBC algorithm.
|
||||
// Corresponds to the cfca.sadk.util.encryptMessageBySM4 method.
|
||||
func EncryptBySM4CBC(plaintext, password []byte) ([]byte, error) {
|
||||
mode, err := NewSM4CBCBlockMode(password, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pkcs7 := padding.NewPKCS7Padding(uint(mode.BlockSize()))
|
||||
plaintext = pkcs7.Pad(plaintext)
|
||||
ciphertext := make([]byte, len(plaintext))
|
||||
mode.CryptBlocks(ciphertext, plaintext)
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// DecryptBySM4CBC decrypts the data with the password using SM4-CBC algorithm.
|
||||
// Corresponds to the cfca.sadk.util.decryptMessageBySM4 method.
|
||||
func DecryptBySM4CBC(ciphertext, password []byte) ([]byte, error) {
|
||||
mode, err := NewSM4CBCBlockMode(password, false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plaintext := make([]byte, len(ciphertext))
|
||||
mode.CryptBlocks(plaintext, ciphertext)
|
||||
pkcs7 := padding.NewPKCS7Padding(uint(mode.BlockSize()))
|
||||
return pkcs7.Unpad(plaintext)
|
||||
}
|
@ -2,18 +2,14 @@
|
||||
package cfca
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"encoding/asn1"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/emmansun/gmsm/padding"
|
||||
"github.com/emmansun/gmsm/pkcs"
|
||||
"github.com/emmansun/gmsm/pkcs7"
|
||||
"github.com/emmansun/gmsm/sm2"
|
||||
"github.com/emmansun/gmsm/sm3"
|
||||
"github.com/emmansun/gmsm/sm4"
|
||||
"github.com/emmansun/gmsm/smx509"
|
||||
)
|
||||
|
||||
@ -59,18 +55,11 @@ func ParseSM2(password, data []byte) (*sm2.PrivateKey, *smx509.Certificate, erro
|
||||
if !keys.EncryptedKey.Algorithm.Equal(oidSM4) && !keys.EncryptedKey.Algorithm.Equal(oidSM4CBC) {
|
||||
return nil, nil, fmt.Errorf("cfca: unsupported algorithm <%v>", keys.EncryptedKey.Algorithm)
|
||||
}
|
||||
ivkey := sm3.Kdf(password, 32)
|
||||
marshalledIV, err := asn1.Marshal(ivkey[:16])
|
||||
pk, err := DecryptBySM4CBC(keys.EncryptedKey.EncryptedContent.Bytes, password)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
pk, err := pkcs.SM4CBC.Decrypt(ivkey[16:], &asn1.RawValue{FullBytes: marshalledIV}, keys.EncryptedKey.EncryptedContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
d := new(big.Int).SetBytes(pk) // here we do NOT check if the d is in (0, N) or not
|
||||
// Create private key from *big.Int
|
||||
prvKey, err := sm2.NewPrivateKeyFromInt(d)
|
||||
prvKey, err := sm2.NewPrivateKeyFromInt(new(big.Int).SetBytes(pk))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
@ -87,22 +76,12 @@ func ParseSM2(password, data []byte) (*sm2.PrivateKey, *smx509.Certificate, erro
|
||||
|
||||
// MarshalSM2 encodes sm2 private key and related certificate to cfca defined format
|
||||
func MarshalSM2(password []byte, key *sm2.PrivateKey, cert *smx509.Certificate) ([]byte, error) {
|
||||
if len(password) == 0 {
|
||||
return nil, errors.New("cfca: invalid password")
|
||||
}
|
||||
ivkey := sm3.Kdf(password, 32)
|
||||
block, err := sm4.NewCipher(ivkey[16:])
|
||||
if err != nil {
|
||||
var err error
|
||||
var ciphertext []byte
|
||||
if ciphertext, err = EncryptBySM4CBC(key.D.Bytes(), password); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mode := cipher.NewCBCEncrypter(block, ivkey[:16])
|
||||
pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize()))
|
||||
plainText := pkcs7.Pad(key.D.Bytes())
|
||||
ciphertext := make([]byte, len(plainText))
|
||||
mode.CryptBlocks(ciphertext, plainText)
|
||||
|
||||
ciphertext, err = asn1.Marshal(ciphertext)
|
||||
if err != nil {
|
||||
if ciphertext, err = asn1.Marshal(ciphertext); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
|
@ -100,8 +100,9 @@ SADK 3.2之后的版本,支持下列SM2密文格式(encryptedType):
|
||||
* 0x04 - C1为非压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。
|
||||
* 0x02/0x03 - C1为压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。
|
||||
|
||||
### 生成双密钥CSR (v0.29.6+)
|
||||
`cfca.CreateCertificateRequest`,和CFCA SADK不同,调用者需要自行先生成两对密钥对,一对用于签名证书,一对用于加解密CFCA生成的加密用私钥文件(CFCA加密,申请者解密)。
|
||||
使用`cfca.ParseEscrowPrivateKey`解析CFCA返回的加密用私钥。
|
||||
|
||||
### SM2私钥、证书的解析
|
||||
这个是CFCA自定义的,未见相关标准,可以通过```cfca.ParseSM2```来解析。
|
||||
|
||||
### 生成双密钥CSR
|
||||
`cfca.CreateCertificateRequest`,和CFCA SADK不同,调用者需要自行先生成两对密钥对,一对用于签名证书,一对用于加解密CFCA生成的加密用私钥文件(CFCA加密,申请者解密)。
|
||||
|
Loading…
x
Reference in New Issue
Block a user