mirror of
https://github.com/emmansun/gmsm.git
synced 2025-05-13 20:46: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
|
ciphers[oid.String()] = cipher
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCipher(oid asn1.ObjectIdentifier) (Cipher, error) {
|
func GetCipher(alg pkix.AlgorithmIdentifier) (Cipher, error) {
|
||||||
newCipher, ok := ciphers[oid.String()]
|
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 {
|
if !ok {
|
||||||
return nil, fmt.Errorf("pkcs: unsupported cipher (OID: %s)", oid)
|
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
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
mode := smcipher.NewECBEncrypter(block)
|
mode := smcipher.NewECBEncrypter(block)
|
||||||
|
pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize()))
|
||||||
|
plaintext = pkcs7.Pad(plaintext)
|
||||||
ciphertext := make([]byte, len(plaintext))
|
ciphertext := make([]byte, len(plaintext))
|
||||||
mode.CryptBlocks(ciphertext, plaintext)
|
mode.CryptBlocks(ciphertext, plaintext)
|
||||||
|
|
||||||
@ -83,10 +93,14 @@ func (ecb *ecbBlockCipher) Decrypt(key []byte, parameters *asn1.RawValue, cipher
|
|||||||
mode := smcipher.NewECBDecrypter(block)
|
mode := smcipher.NewECBDecrypter(block)
|
||||||
plaintext := make([]byte, len(ciphertext))
|
plaintext := make([]byte, len(ciphertext))
|
||||||
mode.CryptBlocks(plaintext, 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 {
|
type cbcBlockCipher struct {
|
||||||
baseBlockCipher
|
baseBlockCipher
|
||||||
ivSize int
|
ivSize int
|
||||||
|
@ -20,23 +20,11 @@ func init() {
|
|||||||
RegisterCipher(oidSM4GCM, func() Cipher {
|
RegisterCipher(oidSM4GCM, func() Cipher {
|
||||||
return SM4GCM
|
return SM4GCM
|
||||||
})
|
})
|
||||||
RegisterCipher(oidSM4, func() Cipher {
|
|
||||||
return SM4
|
|
||||||
})
|
|
||||||
RegisterCipher(oidSM4ECB, func() Cipher {
|
RegisterCipher(oidSM4ECB, func() Cipher {
|
||||||
return SM4ECB
|
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.
|
// SM4ECB is the 128-bit key SM4 cipher in ECB mode.
|
||||||
var SM4ECB = &ecbBlockCipher{
|
var SM4ECB = &ecbBlockCipher{
|
||||||
baseBlockCipher: baseBlockCipher{
|
baseBlockCipher: baseBlockCipher{
|
||||||
|
@ -79,8 +79,7 @@ func (eci encryptedContentInfo) getCiphertext() (ciphertext []byte) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
|
func (eci encryptedContentInfo) decrypt(key []byte) ([]byte, error) {
|
||||||
alg := eci.ContentEncryptionAlgorithm.Algorithm
|
cipher, err := pkcs.GetCipher(eci.ContentEncryptionAlgorithm)
|
||||||
cipher, err := pkcs.GetCipher(alg)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, ErrUnsupportedAlgorithm
|
return nil, ErrUnsupportedAlgorithm
|
||||||
}
|
}
|
||||||
|
@ -169,7 +169,7 @@ func TestCreateSignedEvnvelopedDataSM(t *testing.T) {
|
|||||||
}
|
}
|
||||||
sm2Key.D.FillBytes(privKey)
|
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 {
|
for _, cipher := range testCipers {
|
||||||
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
|
saed, err := NewSMSignedAndEnvelopedData(privKey, cipher)
|
||||||
if err != nil {
|
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")
|
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 {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ var (
|
|||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// This implementation follows GB/T 35276-2017, uses SM4 cipher to encrypt sm2 private key.
|
// 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) {
|
func MarshalEnvelopedPrivateKey(rand io.Reader, pub *ecdsa.PublicKey, tobeEnveloped *PrivateKey) ([]byte, error) {
|
||||||
// encrypt sm2 private key
|
// encrypt sm2 private key
|
||||||
size := (tobeEnveloped.Curve.Params().N.BitLen() + 7) / 8
|
size := (tobeEnveloped.Curve.Params().N.BitLen() + 7) / 8
|
||||||
@ -61,7 +62,7 @@ func MarshalEnvelopedPrivateKey(rand io.Reader, pub *ecdsa.PublicKey, tobeEnvelo
|
|||||||
// marshal the result
|
// marshal the result
|
||||||
var b cryptobyte.Builder
|
var b cryptobyte.Builder
|
||||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(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.AddBytes(encryptedKey)
|
||||||
b.AddASN1BitString(elliptic.Marshal(tobeEnveloped.Curve, tobeEnveloped.X, tobeEnveloped.Y))
|
b.AddASN1BitString(elliptic.Marshal(tobeEnveloped.Curve, tobeEnveloped.X, tobeEnveloped.Y))
|
||||||
b.AddASN1BitString(encryptedPrivateKey)
|
b.AddASN1BitString(encryptedPrivateKey)
|
||||||
@ -114,6 +115,7 @@ func ParseEnvelopedPrivateKey(priv *PrivateKey, enveloped []byte) (*PrivateKey,
|
|||||||
bytes := encryptedPrivateKey.RightAlign()
|
bytes := encryptedPrivateKey.RightAlign()
|
||||||
plaintext := make([]byte, len(bytes))
|
plaintext := make([]byte, len(bytes))
|
||||||
mode.CryptBlocks(plaintext, 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 := new(PrivateKey)
|
||||||
sm2Key.D = new(big.Int).SetBytes(plaintext)
|
sm2Key.D = new(big.Int).SetBytes(plaintext)
|
||||||
sm2Key.Curve = P256()
|
sm2Key.Curve = P256()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user