pkcs: SM4 oid special handling

This commit is contained in:
Sun Yimin 2023-03-27 13:41:45 +08:00 committed by GitHub
parent 1ed0dbb068
commit d814868a47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 24 additions and 21 deletions

View File

@ -33,8 +33,16 @@ func RegisterCipher(oid asn1.ObjectIdentifier, cipher func() Cipher) {
ciphers[oid.String()] = cipher
}
func GetCipher(oid asn1.ObjectIdentifier) (Cipher, error) {
newCipher, ok := ciphers[oid.String()]
func GetCipher(alg pkix.AlgorithmIdentifier) (Cipher, error) {
oid := alg.Algorithm.String()
if oid == oidSM4.String() {
if len(alg.Parameters.Bytes) != 0 {
return SM4CBC, nil
} else {
return SM4ECB, nil
}
}
newCipher, ok := ciphers[oid]
if !ok {
return nil, fmt.Errorf("pkcs: unsupported cipher (OID: %s)", oid)
}
@ -65,6 +73,8 @@ func (ecb *ecbBlockCipher) Encrypt(key, plaintext []byte) (*pkix.AlgorithmIdenti
return nil, nil, err
}
mode := smcipher.NewECBEncrypter(block)
pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize()))
plaintext = pkcs7.Pad(plaintext)
ciphertext := make([]byte, len(plaintext))
mode.CryptBlocks(ciphertext, plaintext)
@ -83,10 +93,14 @@ func (ecb *ecbBlockCipher) Decrypt(key []byte, parameters *asn1.RawValue, cipher
mode := smcipher.NewECBDecrypter(block)
plaintext := make([]byte, len(ciphertext))
mode.CryptBlocks(plaintext, ciphertext)
return plaintext, nil
pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize()))
unpadded, err := pkcs7.Unpad(plaintext)
if err != nil { // In order to be compatible with some implementations without padding
return plaintext, nil
}
return unpadded, nil
}
type cbcBlockCipher struct {
baseBlockCipher
ivSize int

View File

@ -20,23 +20,11 @@ func init() {
RegisterCipher(oidSM4GCM, func() Cipher {
return SM4GCM
})
RegisterCipher(oidSM4, func() Cipher {
return SM4
})
RegisterCipher(oidSM4ECB, func() Cipher {
return SM4ECB
})
}
// SM4 is the 128-bit key SM4 cipher in ECB mode.
var SM4 = &ecbBlockCipher{
baseBlockCipher: baseBlockCipher{
keySize: 16,
newBlock: sm4.NewCipher,
oid: oidSM4,
},
}
// SM4ECB is the 128-bit key SM4 cipher in ECB mode.
var SM4ECB = &ecbBlockCipher{
baseBlockCipher: baseBlockCipher{

View File

@ -79,8 +79,7 @@ func (eci encryptedContentInfo) getCiphertext() (ciphertext []byte) {
}
func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
alg := eci.ContentEncryptionAlgorithm.Algorithm
cipher, err := pkcs.GetCipher(alg)
cipher, err := pkcs.GetCipher(eci.ContentEncryptionAlgorithm)
if err != nil {
return nil, ErrUnsupportedAlgorithm
}

View File

@ -169,7 +169,7 @@ func TestCreateSignedEvnvelopedDataSM(t *testing.T) {
}
sm2Key.D.FillBytes(privKey)
testCipers := []pkcs.Cipher{pkcs.SM4, pkcs.SM4ECB, pkcs.SM4CBC, pkcs.SM4GCM}
testCipers := []pkcs.Cipher{pkcs.SM4ECB, pkcs.SM4CBC, pkcs.SM4GCM}
for _, cipher := range testCipers {
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
if err != nil {

View File

@ -167,7 +167,7 @@ func ParsePrivateKey(der []byte, password []byte) (interface{}, KDFParameters, e
return nil, nil, errors.New("pkcs8: invalid PBES2 parameters")
}
cipher, err := pkcs.GetCipher(params.EncryptionScheme.Algorithm)
cipher, err := pkcs.GetCipher(params.EncryptionScheme)
if err != nil {
return nil, nil, err
}

View File

@ -31,6 +31,7 @@ var (
// }
//
// This implementation follows GB/T 35276-2017, uses SM4 cipher to encrypt sm2 private key.
// Please note the standard did NOT clarify if the ECB mode requires padding or not.
func MarshalEnvelopedPrivateKey(rand io.Reader, pub *ecdsa.PublicKey, tobeEnveloped *PrivateKey) ([]byte, error) {
// encrypt sm2 private key
size := (tobeEnveloped.Curve.Params().N.BitLen() + 7) / 8
@ -61,7 +62,7 @@ func MarshalEnvelopedPrivateKey(rand io.Reader, pub *ecdsa.PublicKey, tobeEnvelo
// marshal the result
var b cryptobyte.Builder
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1ObjectIdentifier(oidSM4) // use oidSM4ECB?
b.AddASN1ObjectIdentifier(oidSM4ECB) // use oidSM4?
b.AddBytes(encryptedKey)
b.AddASN1BitString(elliptic.Marshal(tobeEnveloped.Curve, tobeEnveloped.X, tobeEnveloped.Y))
b.AddASN1BitString(encryptedPrivateKey)
@ -114,6 +115,7 @@ func ParseEnvelopedPrivateKey(priv *PrivateKey, enveloped []byte) (*PrivateKey,
bytes := encryptedPrivateKey.RightAlign()
plaintext := make([]byte, len(bytes))
mode.CryptBlocks(plaintext, bytes)
// Do we need to check length in order to be compatible with some implementations with padding?
sm2Key := new(PrivateKey)
sm2Key.D = new(big.Int).SetBytes(plaintext)
sm2Key.Curve = P256()