mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 04:06:18 +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
|
package cfca
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/cipher"
|
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math/big"
|
"math/big"
|
||||||
|
|
||||||
"github.com/emmansun/gmsm/padding"
|
|
||||||
"github.com/emmansun/gmsm/pkcs"
|
"github.com/emmansun/gmsm/pkcs"
|
||||||
"github.com/emmansun/gmsm/pkcs7"
|
"github.com/emmansun/gmsm/pkcs7"
|
||||||
"github.com/emmansun/gmsm/sm2"
|
"github.com/emmansun/gmsm/sm2"
|
||||||
"github.com/emmansun/gmsm/sm3"
|
|
||||||
"github.com/emmansun/gmsm/sm4"
|
|
||||||
"github.com/emmansun/gmsm/smx509"
|
"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) {
|
if !keys.EncryptedKey.Algorithm.Equal(oidSM4) && !keys.EncryptedKey.Algorithm.Equal(oidSM4CBC) {
|
||||||
return nil, nil, fmt.Errorf("cfca: unsupported algorithm <%v>", keys.EncryptedKey.Algorithm)
|
return nil, nil, fmt.Errorf("cfca: unsupported algorithm <%v>", keys.EncryptedKey.Algorithm)
|
||||||
}
|
}
|
||||||
ivkey := sm3.Kdf(password, 32)
|
pk, err := DecryptBySM4CBC(keys.EncryptedKey.EncryptedContent.Bytes, password)
|
||||||
marshalledIV, err := asn1.Marshal(ivkey[:16])
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
pk, err := pkcs.SM4CBC.Decrypt(ivkey[16:], &asn1.RawValue{FullBytes: marshalledIV}, keys.EncryptedKey.EncryptedContent.Bytes)
|
prvKey, err := sm2.NewPrivateKeyFromInt(new(big.Int).SetBytes(pk))
|
||||||
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)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
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
|
// MarshalSM2 encodes sm2 private key and related certificate to cfca defined format
|
||||||
func MarshalSM2(password []byte, key *sm2.PrivateKey, cert *smx509.Certificate) ([]byte, error) {
|
func MarshalSM2(password []byte, key *sm2.PrivateKey, cert *smx509.Certificate) ([]byte, error) {
|
||||||
if len(password) == 0 {
|
var err error
|
||||||
return nil, errors.New("cfca: invalid password")
|
var ciphertext []byte
|
||||||
}
|
if ciphertext, err = EncryptBySM4CBC(key.D.Bytes(), password); err != nil {
|
||||||
ivkey := sm3.Kdf(password, 32)
|
|
||||||
block, err := sm4.NewCipher(ivkey[16:])
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
mode := cipher.NewCBCEncrypter(block, ivkey[:16])
|
if ciphertext, err = asn1.Marshal(ciphertext); err != nil {
|
||||||
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 {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,8 +100,9 @@ SADK 3.2之后的版本,支持下列SM2密文格式(encryptedType):
|
|||||||
* 0x04 - C1为非压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。
|
* 0x04 - C1为非压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。
|
||||||
* 0x02/0x03 - C1为压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。
|
* 0x02/0x03 - C1为压缩点格式,具体是C1C3C2还是C1C2C3取决于解密时的选项参数,默认为C1C3C2。
|
||||||
|
|
||||||
|
### 生成双密钥CSR (v0.29.6+)
|
||||||
|
`cfca.CreateCertificateRequest`,和CFCA SADK不同,调用者需要自行先生成两对密钥对,一对用于签名证书,一对用于加解密CFCA生成的加密用私钥文件(CFCA加密,申请者解密)。
|
||||||
|
使用`cfca.ParseEscrowPrivateKey`解析CFCA返回的加密用私钥。
|
||||||
|
|
||||||
### SM2私钥、证书的解析
|
### SM2私钥、证书的解析
|
||||||
这个是CFCA自定义的,未见相关标准,可以通过```cfca.ParseSM2```来解析。
|
这个是CFCA自定义的,未见相关标准,可以通过```cfca.ParseSM2```来解析。
|
||||||
|
|
||||||
### 生成双密钥CSR
|
|
||||||
`cfca.CreateCertificateRequest`,和CFCA SADK不同,调用者需要自行先生成两对密钥对,一对用于签名证书,一对用于加解密CFCA生成的加密用私钥文件(CFCA加密,申请者解密)。
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user