Skip to content
This repository has been archived by the owner on Jun 17, 2022. It is now read-only.

Commit

Permalink
Implement real gcm mode
Browse files Browse the repository at this point in the history
  • Loading branch information
Emman committed Apr 11, 2022
1 parent 672e87e commit 03589b6
Show file tree
Hide file tree
Showing 4 changed files with 73 additions and 31 deletions.
44 changes: 36 additions & 8 deletions cipher.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package pkcs8

import (
"bytes"
"crypto/cipher"
"encoding/asn1"

"github.com/emmansun/gmsm/padding"
)

type cipherWithBlock struct {
Expand Down Expand Up @@ -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)
}
36 changes: 21 additions & 15 deletions cipher_aes.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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.
Expand All @@ -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,
},
}
15 changes: 7 additions & 8 deletions cipher_sm4.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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,
},
}
9 changes: 9 additions & 0 deletions pkcs8_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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{
Expand Down

0 comments on commit 03589b6

Please sign in to comment.