sm9: handle empty plaintext and invalid ciphertext size

This commit is contained in:
Sun Yimin 2023-02-14 10:45:02 +08:00 committed by GitHub
parent 94cf65edbe
commit bf037a329e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 91 additions and 15 deletions

View File

@ -39,6 +39,9 @@ func (opts *XOREncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]
}
func (opts *XOREncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
if len(ciphertext) == 0 {
return nil, ErrDecryption
}
subtle.XORBytes(key, ciphertext, key)
return key, nil
}
@ -138,6 +141,9 @@ func (opts *ECBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
if err != nil {
return nil, err
}
if len(ciphertext) == 0 {
return nil, ErrDecryption
}
plaintext := make([]byte, len(ciphertext))
mode := _cipher.NewECBDecrypter(block)
mode.CryptBlocks(plaintext, ciphertext)

46
sm9/enc_mode_test.go Normal file
View File

@ -0,0 +1,46 @@
package sm9
import (
"crypto/rand"
"testing"
)
func TestInvalidKeySize(t *testing.T) {
encOpts := []EncrypterOpts{
SM4ECBEncrypterOpts, SM4CBCEncrypterOpts, SM4CFBEncrypterOpts, SM4OFBEncrypterOpts,
}
for _, opts := range encOpts {
_, err := opts.Encrypt(rand.Reader, []byte("123456789012345"), []byte("plaintext"))
if err.Error() != "sm4: invalid key size 15" {
t.Fatalf("not expected error: %v\n", err.Error())
}
_, err = opts.Decrypt([]byte("123456789012345"), []byte("ciphertext"))
if err.Error() != "sm4: invalid key size 15" {
t.Fatalf("not expected error: %v\n", err.Error())
}
}
}
func TestInvalidCiphertextSize(t *testing.T) {
encOpts := []EncrypterOpts{
SM4CBCEncrypterOpts, SM4CFBEncrypterOpts, SM4OFBEncrypterOpts,
}
for _, opts := range encOpts {
_, err := opts.Decrypt([]byte("1234567890123450"), []byte("ciphertext"))
if err.Error() != "sm9: decryption error" {
t.Fatalf("not expected error: %v\n", err.Error())
}
}
}
func TestEmptyCiphertext(t *testing.T) {
encOpts := []EncrypterOpts{
SM4ECBEncrypterOpts, DefaultEncrypterOpts,
}
for _, opts := range encOpts {
_, err := opts.Decrypt([]byte("1234567890123450"), nil)
if err.Error() != "sm9: decryption error" {
t.Fatalf("not expected error: %v\n", err.Error())
}
}
}

View File

@ -302,7 +302,7 @@ func WrapKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
return
}
// WrapKey wrap key and marshal the cipher as ASN1 format, SM9PublicKey1 definition.
// WrapKey wraps key and converts the cipher as ASN1 format, SM9PublicKey1 definition.
func (pub *EncryptMasterPublicKey) WrapKey(rand io.Reader, uid []byte, hid byte, kLen int) ([]byte, []byte, error) {
key, cipher, err := WrapKey(rand, pub, uid, hid, kLen)
if err != nil {
@ -315,7 +315,7 @@ func (pub *EncryptMasterPublicKey) WrapKey(rand io.Reader, uid []byte, hid byte,
return key, cipherASN1, err
}
// WrapKeyASN1 wrap key and marshal the result of SM9KeyPackage as ASN1 format. according
// WrapKeyASN1 wraps key and converts the result of SM9KeyPackage as ASN1 format. according
// SM9 cryptographic algorithm application specification, SM9KeyPackage defnition.
func (pub *EncryptMasterPublicKey) WrapKeyASN1(rand io.Reader, uid []byte, hid byte, kLen int) ([]byte, error) {
key, cipher, err := WrapKey(rand, pub, uid, hid, kLen)
@ -356,7 +356,10 @@ func UnmarshalSM9KeyPackage(der []byte) ([]byte, *bn256.G1, error) {
// It is deliberately vague to avoid adaptive attacks.
var ErrDecryption = errors.New("sm9: decryption error")
// UnwrapKey unwrap key from cipher, user id and aligned key length
// ErrEmptyPlaintext represents a failure to encrypt an empty message.
var ErrEmptyPlaintext = errors.New("sm9: empty plaintext")
// UnwrapKey unwraps key from cipher, user id and aligned key length
func UnwrapKey(priv *EncryptPrivateKey, uid []byte, cipher *bn256.G1, kLen int) ([]byte, error) {
if !cipher.IsOnCurve() {
return nil, ErrDecryption
@ -376,7 +379,7 @@ func UnwrapKey(priv *EncryptPrivateKey, uid []byte, cipher *bn256.G1, kLen int)
return key, nil
}
// UnwrapKey unwrap key from cipherDer, user id and aligned key length.
// UnwrapKey unwraps key from cipherDer, user id and aligned key length.
// cipherDer is SM9PublicKey1 format according SM9 cryptographic algorithm application specification.
func (priv *EncryptPrivateKey) UnwrapKey(uid, cipherDer []byte, kLen int) ([]byte, error) {
var bytes []byte
@ -391,7 +394,7 @@ func (priv *EncryptPrivateKey) UnwrapKey(uid, cipherDer []byte, kLen int) ([]byt
return UnwrapKey(priv, uid, g, kLen)
}
// Encrypt encrypt plaintext, output ciphertext with format C1||C3||C2.
// Encrypt encrypts plaintext, returns ciphertext with format C1||C3||C2.
func Encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte, opts EncrypterOpts) ([]byte, error) {
c1, c2, c3, err := encrypt(rand, pub, uid, hid, plaintext, opts)
if err != nil {
@ -406,6 +409,9 @@ func encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
if opts == nil {
opts = DefaultEncrypterOpts
}
if len(plaintext) == 0 {
return nil, nil, nil, ErrEmptyPlaintext
}
key1Len := opts.GetKeySize(plaintext)
key, c1, err := WrapKey(rand, pub, uid, hid, key1Len+sm3.Size)
if err != nil {
@ -424,13 +430,13 @@ func encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
return
}
// EncryptASN1 encrypt plaintext and output ciphertext with ASN.1 format according
// EncryptASN1 encrypts plaintext and returns ciphertext with ASN.1 format according
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
func EncryptASN1(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte, opts EncrypterOpts) ([]byte, error) {
return pub.Encrypt(rand, uid, hid, plaintext, opts)
}
// Encrypt encrypt plaintext and output ciphertext with ASN.1 format according
// Encrypt encrypts plaintext and returns ciphertext with ASN.1 format according
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte, plaintext []byte, opts EncrypterOpts) ([]byte, error) {
if opts == nil {
@ -451,7 +457,7 @@ func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte,
return b.Bytes()
}
// Decrypt decrypt chipher, ciphertext should be with format C1||C3||C2
// Decrypt decrypts chipher, the ciphertext should be with format C1||C3||C2
func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte, opts EncrypterOpts) ([]byte, error) {
if opts == nil {
opts = DefaultEncrypterOpts
@ -487,7 +493,7 @@ func decrypt(cipher *bn256.G1, key1, key2, c2, c3 []byte, opts EncrypterOpts) ([
return opts.Decrypt(key1, c2)
}
// DecryptASN1 decrypt chipher, ciphertext should be with ASN.1 format according
// DecryptASN1 decrypts chipher, the ciphertext should be with ASN.1 format according
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error) {
if len(ciphertext) <= 32+65 {
@ -529,18 +535,18 @@ func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error
return decrypt(c, key[:key1Len], key[key1Len:], c2Bytes, c3Bytes, opts)
}
// Decrypt decrypt chipher, ciphertext should be with format C1||C3||C2
// Decrypt decrypts chipher, the ciphertext should be with format C1||C3||C2
func (priv *EncryptPrivateKey) Decrypt(uid, ciphertext []byte, opts EncrypterOpts) ([]byte, error) {
return Decrypt(priv, uid, ciphertext, opts)
}
// DecryptASN1 decrypt chipher, ciphertext should be with ASN.1 format according
// DecryptASN1 decrypts chipher, the ciphertext should be with ASN.1 format according
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
func (priv *EncryptPrivateKey) DecryptASN1(uid, ciphertext []byte) ([]byte, error) {
return DecryptASN1(priv, uid, ciphertext)
}
// KeyExchange key exchange struct, include internal stat in whole key exchange flow.
// KeyExchange represents key exchange struct, include internal stat in whole key exchange flow.
// Initiator's flow will be: NewKeyExchange -> InitKeyExchange -> transmission -> ConfirmResponder
// Responder's flow will be: NewKeyExchange -> waiting ... -> RepondKeyExchange -> transmission -> ConfirmInitiator
type KeyExchange struct {
@ -557,7 +563,7 @@ type KeyExchange struct {
g3 *bn256.GT // internal state which will be used when compute the key and signature
}
// NewKeyExchange create one new KeyExchange object
// NewKeyExchange creates one new KeyExchange object
func NewKeyExchange(priv *EncryptPrivateKey, uid, peerUID []byte, keyLen int, genSignature bool) *KeyExchange {
ke := &KeyExchange{}
ke.genSignature = genSignature
@ -568,7 +574,7 @@ func NewKeyExchange(priv *EncryptPrivateKey, uid, peerUID []byte, keyLen int, ge
return ke
}
// Destroy clear all internal state and Ephemeral private/public keys
// Destroy clears all internal state and Ephemeral private/public keys
func (ke *KeyExchange) Destroy() {
if ke.r != nil {
ke.r.SetBytes([]byte{0}, orderNat)
@ -594,7 +600,7 @@ func initKeyExchange(ke *KeyExchange, hid byte, r *bigmod.Nat) {
ke.secret = rA
}
// InitKeyExchange generate random with responder uid, for initiator's step A1-A4
// InitKeyExchange generates random with responder uid, for initiator's step A1-A4
func (ke *KeyExchange) InitKeyExchange(rand io.Reader, hid byte) (*bn256.G1, error) {
r, err := randomScalar(rand)
if err != nil {

View File

@ -759,6 +759,24 @@ func TestEncryptDecrypt(t *testing.T) {
}
}
func TestEncryptEmptyPlaintext(t *testing.T) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
hid := byte(0x01)
uid := []byte("emmansun")
if err != nil {
t.Fatal(err)
}
encTypes := []EncrypterOpts{
DefaultEncrypterOpts, SM4ECBEncrypterOpts, SM4CBCEncrypterOpts, SM4CFBEncrypterOpts, SM4OFBEncrypterOpts,
}
for _, opts := range encTypes {
_, err := Encrypt(rand.Reader, masterKey.Public(), uid, hid, nil, opts)
if err != ErrEmptyPlaintext {
t.Fatalf("should be ErrEmptyPlaintext")
}
}
}
func TestEncryptDecryptASN1(t *testing.T) {
plaintext := []byte("Chinese IBE standard")
masterKey, err := GenerateEncryptMasterKey(rand.Reader)