mirror of
https://github.com/emmansun/gmsm.git
synced 2025-05-12 03:56:17 +08:00
pkcs: SM4 oid special handling
This commit is contained in:
parent
1ed0dbb068
commit
d814868a47
@ -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
|
||||
|
@ -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{
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
Loading…
x
Reference in New Issue
Block a user