diff --git a/cipher.go b/cipher.go index 2946c93..f8e67ef 100644 --- a/cipher.go +++ b/cipher.go @@ -1,9 +1,10 @@ package pkcs8 import ( - "bytes" "crypto/cipher" "encoding/asn1" + + "github.com/emmansun/gmsm/padding" ) type cipherWithBlock struct { @@ -43,18 +44,45 @@ func (c cipherWithBlock) Decrypt(key, iv, ciphertext []byte) ([]byte, error) { func cbcEncrypt(block cipher.Block, key, iv, plaintext []byte) ([]byte, error) { mode := cipher.NewCBCEncrypter(block, iv) - paddingLen := block.BlockSize() - (len(plaintext) % block.BlockSize()) - ciphertext := make([]byte, len(plaintext)+paddingLen) - copy(ciphertext, plaintext) - copy(ciphertext[len(plaintext):], bytes.Repeat([]byte{byte(paddingLen)}, paddingLen)) - mode.CryptBlocks(ciphertext, ciphertext) + pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize())) + plainText := pkcs7.Pad(plaintext) + ciphertext := make([]byte, len(plainText)) + mode.CryptBlocks(ciphertext, plainText) return ciphertext, nil } func cbcDecrypt(block cipher.Block, key, iv, ciphertext []byte) ([]byte, error) { mode := cipher.NewCBCDecrypter(block, iv) + pkcs7 := padding.NewPKCS7Padding(uint(block.BlockSize())) plaintext := make([]byte, len(ciphertext)) mode.CryptBlocks(plaintext, ciphertext) - // TODO: remove padding - return plaintext, nil + return pkcs7.Unpad(plaintext) +} + +type cipherWithGCM struct { + cipherWithBlock +} + +func (c cipherWithGCM) Encrypt(key, iv, plaintext []byte) ([]byte, error) { + block, err := c.newBlock(key) + if err != nil { + return nil, err + } + aead, err := cipher.NewGCMWithNonceSize(block, len(iv)) + if err != nil { + return nil, err + } + return aead.Seal(nil, iv, plaintext, nil), nil +} + +func (c cipherWithGCM) Decrypt(key, iv, ciphertext []byte) ([]byte, error) { + block, err := c.newBlock(key) + if err != nil { + return nil, err + } + aead, err := cipher.NewGCMWithNonceSize(block, len(iv)) + if err != nil { + return nil, err + } + return aead.Open(nil, iv, ciphertext, nil) } diff --git a/cipher_aes.go b/cipher_aes.go index c0372d1..734790f 100644 --- a/cipher_aes.go +++ b/cipher_aes.go @@ -44,11 +44,13 @@ var AES128CBC = cipherWithBlock{ } // AES128GCM is the 128-bit key AES cipher in GCM mode. -var AES128GCM = cipherWithBlock{ - ivSize: aes.BlockSize, - keySize: 16, - newBlock: aes.NewCipher, - oid: oidAES128GCM, +var AES128GCM = cipherWithGCM{ + cipherWithBlock: cipherWithBlock{ + ivSize: 12, + keySize: 16, + newBlock: aes.NewCipher, + oid: oidAES128GCM, + }, } // AES192CBC is the 192-bit key AES cipher in CBC mode. @@ -60,11 +62,13 @@ var AES192CBC = cipherWithBlock{ } // AES192GCM is the 912-bit key AES cipher in GCM mode. -var AES192GCM = cipherWithBlock{ - ivSize: aes.BlockSize, - keySize: 24, - newBlock: aes.NewCipher, - oid: oidAES192GCM, +var AES192GCM = cipherWithGCM{ + cipherWithBlock: cipherWithBlock{ + ivSize: 12, + keySize: 24, + newBlock: aes.NewCipher, + oid: oidAES192GCM, + }, } // AES256CBC is the 256-bit key AES cipher in CBC mode. @@ -76,9 +80,11 @@ var AES256CBC = cipherWithBlock{ } // AES256GCM is the 256-bit key AES cipher in GCM mode. -var AES256GCM = cipherWithBlock{ - ivSize: aes.BlockSize, - keySize: 32, - newBlock: aes.NewCipher, - oid: oidAES256GCM, +var AES256GCM = cipherWithGCM{ + cipherWithBlock: cipherWithBlock{ + ivSize: 12, + keySize: 32, + newBlock: aes.NewCipher, + oid: oidAES256GCM, + }, } diff --git a/cipher_sm4.go b/cipher_sm4.go index 89e480e..05d16e3 100644 --- a/cipher_sm4.go +++ b/cipher_sm4.go @@ -11,16 +11,13 @@ var ( oidSM4GCM = asn1.ObjectIdentifier{1, 2, 156, 10197, 1, 104, 8} ) - func init() { RegisterCipher(oidSM4CBC, func() Cipher { return SM4CBC }) - /* GCM mode usage is incorrect in this module RegisterCipher(oidSM4GCM, func() Cipher { return SM4GCM }) - */ } // SM4CBC is the 128-bit key SM4 cipher in CBC mode. @@ -32,9 +29,11 @@ var SM4CBC = cipherWithBlock{ } // SM4GCM is the 128-bit key SM4 cipher in GCM mode. -var SM4GCM = cipherWithBlock{ - ivSize: sm4.BlockSize, - keySize: 16, - newBlock: sm4.NewCipher, - oid: oidSM4GCM, +var SM4GCM = cipherWithGCM{ + cipherWithBlock: cipherWithBlock{ + ivSize: 12, + keySize: 16, + newBlock: sm4.NewCipher, + oid: oidSM4GCM, + }, } diff --git a/pkcs8_test.go b/pkcs8_test.go index 45f5548..7096c62 100644 --- a/pkcs8_test.go +++ b/pkcs8_test.go @@ -405,6 +405,15 @@ func TestMarshalPrivateKey(t *testing.T) { }, }, }, + { + password: []byte("password"), + opts: &pkcs8.Opts{ + Cipher: pkcs8.SM4GCM, + KDFOpts: pkcs8.PBKDF2Opts{ + SaltSize: 8, IterationCount: 2048, HMACHash: pkcs8.SM3, + }, + }, + }, { password: []byte("password"), opts: &pkcs8.Opts{