sm9: refactor encrypter mode

This commit is contained in:
Sun Yimin 2023-02-13 14:36:34 +08:00 committed by GitHub
parent ebf9a74d77
commit aedef9d00d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 357 additions and 190 deletions

266
sm9/enc_mode.go Normal file
View File

@ -0,0 +1,266 @@
package sm9
import (
"crypto/cipher"
"io"
_cipher "github.com/emmansun/gmsm/cipher"
"github.com/emmansun/gmsm/internal/subtle"
"github.com/emmansun/gmsm/padding"
"github.com/emmansun/gmsm/sm4"
)
// EncrypterOpts is an interface implemented by detail encrypt/decrypt mode.
type EncrypterOpts interface {
// GetEncryptType returns the encrypt type/mode.
GetEncryptType() encryptType
// GetKeySize returns key size used by this encrypt mode.
GetKeySize(plaintext []byte) int
// Encrypt encrypts the plaintext with the key, returns ciphertext.
Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error)
// Decrypt decrypts the ciphertext with the key, returns plaintext.
Decrypt(key, ciphertext []byte) ([]byte, error)
}
// XOREncrypterOpts represents XOR encrypt type/mode.
type XOREncrypterOpts struct{}
func (opts *XOREncrypterOpts) GetEncryptType() encryptType {
return ENC_TYPE_XOR
}
func (opts *XOREncrypterOpts) GetKeySize(plaintext []byte) int {
return len(plaintext)
}
func (opts *XOREncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
subtle.XORBytes(key, key, plaintext)
return key, nil
}
func (opts *XOREncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
subtle.XORBytes(key, ciphertext, key)
return key, nil
}
type CipherFactory func(key []byte) (cipher.Block, error)
type baseBlockEncrypterOpts struct {
encryptType encryptType
cipherFactory CipherFactory
cipherKeySize int
}
func (opts *baseBlockEncrypterOpts) GetEncryptType() encryptType {
return opts.encryptType
}
func (opts *baseBlockEncrypterOpts) GetKeySize(plaintext []byte) int {
return opts.cipherKeySize
}
type CBCEncrypterOpts struct {
baseBlockEncrypterOpts
padding padding.Padding
}
func NewCBCEncrypterOpts(padding padding.Padding, cipherFactory CipherFactory, keySize int) EncrypterOpts {
opts := new(CBCEncrypterOpts)
opts.encryptType = ENC_TYPE_CBC
opts.padding = padding
opts.cipherFactory = cipherFactory
opts.cipherKeySize = keySize
return opts
}
func (opts *CBCEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
paddedPlainText := opts.padding.Pad(plaintext)
blockSize := block.BlockSize()
ciphertext := make([]byte, blockSize+len(paddedPlainText))
iv := ciphertext[:blockSize]
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[blockSize:], paddedPlainText)
return ciphertext, nil
}
func (opts *CBCEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext) < blockSize {
return nil, ErrDecryption
}
iv := ciphertext[:blockSize]
ciphertext = ciphertext[blockSize:]
plaintext := make([]byte, len(ciphertext))
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(plaintext, ciphertext)
return opts.padding.Unpad(plaintext)
}
type ECBEncrypterOpts struct {
baseBlockEncrypterOpts
padding padding.Padding
}
func NewECBEncrypterOpts(padding padding.Padding, cipherFactory CipherFactory, keySize int) EncrypterOpts {
opts := new(ECBEncrypterOpts)
opts.encryptType = ENC_TYPE_ECB
opts.padding = padding
opts.cipherFactory = cipherFactory
opts.cipherKeySize = keySize
return opts
}
func (opts *ECBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
paddedPlainText := opts.padding.Pad(plaintext)
ciphertext := make([]byte, len(paddedPlainText))
mode := _cipher.NewECBEncrypter(block)
mode.CryptBlocks(ciphertext, paddedPlainText)
return ciphertext, nil
}
func (opts *ECBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
plaintext := make([]byte, len(ciphertext))
mode := _cipher.NewECBDecrypter(block)
mode.CryptBlocks(plaintext, ciphertext)
return opts.padding.Unpad(plaintext)
}
type CFBEncrypterOpts struct {
baseBlockEncrypterOpts
}
func NewCFBEncrypterOpts(cipherFactory CipherFactory, keySize int) EncrypterOpts {
opts := new(CFBEncrypterOpts)
opts.encryptType = ENC_TYPE_CFB
opts.cipherFactory = cipherFactory
opts.cipherKeySize = keySize
return opts
}
func (opts *CFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
ciphertext := make([]byte, blockSize+len(plaintext))
iv := ciphertext[:blockSize]
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[blockSize:], plaintext)
return ciphertext, nil
}
func (opts *CFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext) < blockSize {
return nil, ErrDecryption
}
iv := ciphertext[:blockSize]
ciphertext = ciphertext[blockSize:]
plaintext := make([]byte, len(ciphertext))
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(plaintext, ciphertext)
return plaintext, nil
}
type OFBEncrypterOpts struct {
baseBlockEncrypterOpts
}
func NewOFBEncrypterOpts(cipherFactory CipherFactory, keySize int) EncrypterOpts {
opts := new(OFBEncrypterOpts)
opts.encryptType = ENC_TYPE_OFB
opts.cipherFactory = cipherFactory
opts.cipherKeySize = keySize
return opts
}
func (opts *OFBEncrypterOpts) Encrypt(rand io.Reader, key, plaintext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
ciphertext := make([]byte, blockSize+len(plaintext))
iv := ciphertext[:blockSize]
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, err
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(ciphertext[blockSize:], plaintext)
return ciphertext, nil
}
func (opts *OFBEncrypterOpts) Decrypt(key, ciphertext []byte) ([]byte, error) {
block, err := opts.cipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext) < blockSize {
return nil, ErrDecryption
}
iv := ciphertext[:blockSize]
ciphertext = ciphertext[blockSize:]
plaintext := make([]byte, len(ciphertext))
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(plaintext, ciphertext)
return plaintext, nil
}
// DefaultEncrypterOpts default option represents XOR mode
var DefaultEncrypterOpts = new(XOREncrypterOpts)
// SM4ECBEncrypterOpts option represents SM4 ECB mode
var SM4ECBEncrypterOpts = NewECBEncrypterOpts(padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
// SM4CBCEncrypterOpts option represents SM4 CBC mode
var SM4CBCEncrypterOpts = NewCBCEncrypterOpts(padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
// SM4CFBEncrypterOpts option represents SM4 CFB mode
var SM4CFBEncrypterOpts = NewCFBEncrypterOpts(sm4.NewCipher, sm4.BlockSize)
// SM4OFBEncrypterOpts option represents SM4 OFB mode
var SM4OFBEncrypterOpts = NewOFBEncrypterOpts(sm4.NewCipher, sm4.BlockSize)
func shangMiEncrypterOpts(encType encryptType) EncrypterOpts {
switch encType {
case ENC_TYPE_XOR:
return DefaultEncrypterOpts
case ENC_TYPE_CBC:
return SM4CBCEncrypterOpts
case ENC_TYPE_ECB:
return SM4ECBEncrypterOpts
case ENC_TYPE_CFB:
return SM4CFBEncrypterOpts
case ENC_TYPE_OFB:
return SM4OFBEncrypterOpts
}
return nil
}

View File

@ -3,21 +3,16 @@ package sm9
import (
"crypto"
"crypto/cipher"
goSubtle "crypto/subtle"
"encoding/binary"
"errors"
"fmt"
"io"
"math/big"
_cipher "github.com/emmansun/gmsm/cipher"
"github.com/emmansun/gmsm/internal/bigmod"
"github.com/emmansun/gmsm/internal/subtle"
"github.com/emmansun/gmsm/kdf"
"github.com/emmansun/gmsm/padding"
"github.com/emmansun/gmsm/sm3"
"github.com/emmansun/gmsm/sm4"
"github.com/emmansun/gmsm/sm9/bn256"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
@ -396,52 +391,8 @@ func (priv *EncryptPrivateKey) UnwrapKey(uid, cipherDer []byte, kLen int) ([]byt
return UnwrapKey(priv, uid, g, kLen)
}
type CipherFactory func(key []byte) (cipher.Block, error)
// EncrypterOpts indicate encrypt/decrypt options
type EncrypterOpts struct {
EncryptType encryptType
Padding padding.Padding
CipherFactory CipherFactory
CipherKeySize int
}
type DecrypterOpts EncrypterOpts
func (opts *EncrypterOpts) getKeySize(plaintext []byte) int {
if opts.EncryptType == ENC_TYPE_XOR {
return len(plaintext)
}
return opts.CipherKeySize
}
// NewEncrypterOpts creates EncrypterOpts with given parameters
func NewEncrypterOpts(encType encryptType, padMode padding.Padding, factory CipherFactory, cipherKeySize int) *EncrypterOpts {
opts := new(EncrypterOpts)
opts.EncryptType = encType
opts.Padding = padMode
opts.CipherFactory = factory
opts.CipherKeySize = cipherKeySize
return opts
}
// DefaultEncrypterOpts default option represents XOR mode
var DefaultEncrypterOpts = NewEncrypterOpts(ENC_TYPE_XOR, nil, nil, 0)
// SM4ECBEncrypterOpts option represents SM4 ECB mode
var SM4ECBEncrypterOpts = NewEncrypterOpts(ENC_TYPE_ECB, padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
// SM4CBCEncrypterOpts option represents SM4 CBC mode
var SM4CBCEncrypterOpts = NewEncrypterOpts(ENC_TYPE_CBC, padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
// SM4CFBEncrypterOpts option represents SM4 CFB mode
var SM4CFBEncrypterOpts = NewEncrypterOpts(ENC_TYPE_CFB, padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
// SM4OFBEncrypterOpts option represents SM4 OFB mode
var SM4OFBEncrypterOpts = NewEncrypterOpts(ENC_TYPE_OFB, padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
// Encrypt encrypt plaintext, output ciphertext with format C1||C3||C2.
func Encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte, opts *EncrypterOpts) ([]byte, error) {
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 {
return nil, err
@ -451,16 +402,16 @@ func Encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
return ciphertext, nil
}
func encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte, opts *EncrypterOpts) (c1 *bn256.G1, c2, c3 []byte, err error) {
func encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte, opts EncrypterOpts) (c1 *bn256.G1, c2, c3 []byte, err error) {
if opts == nil {
opts = DefaultEncrypterOpts
}
key1Len := opts.getKeySize(plaintext)
key1Len := opts.GetKeySize(plaintext)
key, c1, err := WrapKey(rand, pub, uid, hid, key1Len+sm3.Size)
if err != nil {
return nil, nil, nil, err
}
c2, err = encryptPlaintext(rand, key[:key1Len], plaintext, opts)
c2, err = opts.Encrypt(rand, key[:key1Len], plaintext)
if err != nil {
return nil, nil, nil, err
}
@ -473,77 +424,15 @@ func encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
return
}
func encryptPlaintext(rand io.Reader, key, plaintext []byte, opts *EncrypterOpts) ([]byte, error) {
switch opts.EncryptType {
case ENC_TYPE_XOR:
subtle.XORBytes(key, key, plaintext)
return key, nil
case ENC_TYPE_ECB:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
paddedPlainText := opts.Padding.Pad(plaintext)
ciphertext := make([]byte, len(paddedPlainText))
mode := _cipher.NewECBEncrypter(block)
mode.CryptBlocks(ciphertext, paddedPlainText)
return ciphertext, nil
case ENC_TYPE_CBC:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
paddedPlainText := opts.Padding.Pad(plaintext)
blockSize := block.BlockSize()
ciphertext := make([]byte, blockSize+len(paddedPlainText))
iv := ciphertext[:blockSize]
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, err
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(ciphertext[blockSize:], paddedPlainText)
return ciphertext, nil
case ENC_TYPE_CFB:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
ciphertext := make([]byte, blockSize+len(plaintext))
iv := ciphertext[:blockSize]
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, err
}
stream := cipher.NewCFBEncrypter(block, iv)
stream.XORKeyStream(ciphertext[blockSize:], plaintext)
return ciphertext, nil
case ENC_TYPE_OFB:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
ciphertext := make([]byte, blockSize+len(plaintext))
iv := ciphertext[:blockSize]
if _, err := io.ReadFull(rand, iv); err != nil {
return nil, err
}
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(ciphertext[blockSize:], plaintext)
return ciphertext, nil
}
return nil, fmt.Errorf("sm9: unsupported encryption type <%v>", opts.EncryptType)
}
// EncryptASN1 encrypt plaintext and output 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) {
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
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte, plaintext []byte, opts *EncrypterOpts) ([]byte, error) {
func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte, plaintext []byte, opts EncrypterOpts) ([]byte, error) {
if opts == nil {
opts = DefaultEncrypterOpts
}
@ -554,7 +443,7 @@ func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte,
var b cryptobyte.Builder
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1Int64(int64(opts.EncryptType))
b.AddASN1Int64(int64(opts.GetEncryptType()))
b.AddASN1BitString(c1.MarshalUncompressed())
b.AddASN1OctetString(c3)
b.AddASN1OctetString(c2)
@ -563,7 +452,7 @@ func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte,
}
// Decrypt decrypt chipher, ciphertext should be with format C1||C3||C2
func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte, opts *EncrypterOpts) ([]byte, error) {
func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte, opts EncrypterOpts) ([]byte, error) {
if opts == nil {
opts = DefaultEncrypterOpts
}
@ -575,7 +464,7 @@ func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte, opts *EncrypterOpt
}
c2 := c3c2[sm3.Size:]
key1Len := opts.getKeySize(c2)
key1Len := opts.GetKeySize(c2)
key, err := UnwrapKey(priv, uid, c, key1Len+sm3.Size)
if err != nil {
@ -585,7 +474,7 @@ func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte, opts *EncrypterOpt
return decrypt(c, key[:key1Len], key[key1Len:], c2, c3c2[:sm3.Size], opts)
}
func decrypt(cipher *bn256.G1, key1, key2, c2, c3 []byte, opts *EncrypterOpts) ([]byte, error) {
func decrypt(cipher *bn256.G1, key1, key2, c2, c3 []byte, opts EncrypterOpts) ([]byte, error) {
hash := sm3.New()
hash.Write(c2)
hash.Write(key2)
@ -595,70 +484,7 @@ func decrypt(cipher *bn256.G1, key1, key2, c2, c3 []byte, opts *EncrypterOpts) (
return nil, ErrDecryption
}
return decryptCiphertext(key1, c2, opts)
}
func decryptCiphertext(key, ciphertext []byte, opts *EncrypterOpts) ([]byte, error) {
switch opts.EncryptType {
case ENC_TYPE_XOR:
subtle.XORBytes(key, ciphertext, key)
return key, nil
case ENC_TYPE_ECB:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
plaintext := make([]byte, len(ciphertext))
mode := _cipher.NewECBDecrypter(block)
mode.CryptBlocks(plaintext, ciphertext)
return opts.Padding.Unpad(plaintext)
case ENC_TYPE_CBC:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext) < blockSize {
return nil, ErrDecryption
}
iv := ciphertext[:blockSize]
ciphertext = ciphertext[blockSize:]
plaintext := make([]byte, len(ciphertext))
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(plaintext, ciphertext)
return opts.Padding.Unpad(plaintext)
case ENC_TYPE_CFB:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext) < blockSize {
return nil, ErrDecryption
}
iv := ciphertext[:blockSize]
ciphertext = ciphertext[blockSize:]
plaintext := make([]byte, len(ciphertext))
stream := cipher.NewCFBDecrypter(block, iv)
stream.XORKeyStream(plaintext, ciphertext)
return plaintext, nil
case ENC_TYPE_OFB:
block, err := opts.CipherFactory(key)
if err != nil {
return nil, err
}
blockSize := block.BlockSize()
if len(ciphertext) < blockSize {
return nil, ErrDecryption
}
iv := ciphertext[:blockSize]
ciphertext = ciphertext[blockSize:]
plaintext := make([]byte, len(ciphertext))
stream := cipher.NewOFB(block, iv)
stream.XORKeyStream(plaintext, ciphertext)
return plaintext, nil
}
return nil, fmt.Errorf("sm9: unsupported encryption type <%v>", opts.EncryptType)
return opts.Decrypt(key1, c2)
}
// DecryptASN1 decrypt chipher, ciphertext should be with ASN.1 format according
@ -685,13 +511,16 @@ func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error
return nil, errors.New("sm9: invalid ciphertext asn.1 data")
}
// We just make assumption block cipher is SM4 and padding scheme is pkcs7
opts := NewEncrypterOpts(encryptType(encType), padding.NewPKCS7Padding(sm4.BlockSize), sm4.NewCipher, sm4.BlockSize)
opts := shangMiEncrypterOpts(encryptType(encType))
if opts == nil {
return nil, ErrDecryption
}
c, err := unmarshalG1(c1Bytes)
if err != nil {
return nil, ErrDecryption
}
key1Len := opts.getKeySize(c2Bytes)
key1Len := opts.GetKeySize(c2Bytes)
key, err := UnwrapKey(priv, uid, c, key1Len+sm3.Size)
if err != nil {
return nil, err
@ -702,7 +531,7 @@ func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error
// Decrypt decrypt chipher, ciphertext should be with ASN.1 format according
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
func (priv *EncryptPrivateKey) Decrypt(uid, ciphertext []byte, opts *EncrypterOpts) ([]byte, error) {
func (priv *EncryptPrivateKey) Decrypt(uid, ciphertext []byte, opts EncrypterOpts) ([]byte, error) {
if ciphertext[0] == 0x30 { // should be ASN.1 format
return DecryptASN1(priv, uid, ciphertext)
}

View File

@ -647,6 +647,78 @@ func TestEncryptSM9Sample(t *testing.T) {
}
}
func TestEncryptSM9SampleBlockMode(t *testing.T) {
plaintext := []byte("Chinese IBE standard")
expectedMasterPublicKey := "787ed7b8a51f3ab84e0a66003f32da5c720b17eca7137d39abc66e3c80a892ff769de61791e5adc4b9ff85a31354900b202871279a8c49dc3f220f644c57a7b1"
expectedUserPrivateKey := "94736acd2c8c8796cc4785e938301a139a059d3537b6414140b2d31eecf41683115bae85f5d8bc6c3dbd9e5342979acccf3c2f4f28420b1cb4f8c0b59a19b1587aa5e47570da7600cd760a0cf7beaf71c447f3844753fe74fa7ba92ca7d3b55f27538a62e7f7bfb51dce08704796d94c9d56734f119ea44732b50e31cdeb75c1"
expectedUserPublicKey := "709d165808b0a43e2574e203fa885abcbab16a240c4c1916552e7c43d09763b8693269a6be2456f43333758274786b6051ff87b7f198da4ba1a2c6e336f51fcc"
expectedCipher := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0"
expectedKey := "58373260f067ec48667c21c144f8bc33cd3049788651ffd5f738003e51df31174d0e4e402fd87f4581b612f74259db57"
expectedCiphertext := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0fd3c98dd92c44c68332675a370cceede31e0c5cd209c257601149d12b394a2bee05b6fac6f11b965268c994f00dba7a8bb00fd60583546cbdf4649250863f10a"
masterKey, err := encryptMasterPrivateKeyFromHex("01EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22")
if err != nil {
t.Fatal(err)
}
if hex.EncodeToString(masterKey.MasterPublicKey.Marshal()) != expectedMasterPublicKey {
t.Errorf("not expected master public key")
}
uid := []byte("Bob")
hid := byte(0x03)
userKey, err := masterKey.GenerateUserKey(uid, hid)
if err != nil {
t.Fatal(err)
}
if hex.EncodeToString(userKey.PrivateKey.Marshal()) != expectedUserPrivateKey {
t.Errorf("not expected user private key")
}
q := masterKey.Public().GenerateUserPublicKey(uid, hid)
if hex.EncodeToString(q.Marshal()) != expectedUserPublicKey {
t.Errorf("not expected user public key")
}
var r *big.Int = bigFromHex("AAC0541779C8FC45E3E2CB25C12B5D2576B2129AE8BB5EE2CBE5EC9E785C")
cipher, err := new(bn256.G1).ScalarMult(q, bn256.NormalizeScalar(r.Bytes()))
if err != nil {
t.Fatal(err)
}
if hex.EncodeToString(cipher.Marshal()) != expectedCipher {
t.Errorf("not expected cipher")
}
g := bn256.Pair(masterKey.Public().MasterPublicKey, bn256.Gen2)
w := new(bn256.GT).ScalarMult(g, r)
var buffer []byte
buffer = append(buffer, cipher.Marshal()...)
buffer = append(buffer, w.Marshal()...)
buffer = append(buffer, uid...)
key := kdf.Kdf(sm3.New(), buffer, 16+32)
if hex.EncodeToString(key) != expectedKey {
t.Errorf("not expected key, expected %v, got %x\n", expectedKey, key)
}
c2, err := SM4ECBEncrypterOpts.Encrypt(nil, key[:16], plaintext)
if err != nil {
t.Fatal(err)
}
hash := sm3.New()
hash.Write(c2)
hash.Write(key[16:])
c3 := hash.Sum(nil)
ciphertext := append(cipher.Marshal(), c3...)
ciphertext = append(ciphertext, c2...)
if hex.EncodeToString(ciphertext) != expectedCiphertext {
t.Errorf("expected %v, got %v\n", expectedCiphertext, hex.EncodeToString(ciphertext))
}
}
func TestEncryptDecrypt(t *testing.T) {
plaintext := []byte("Chinese IBE standard")
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
@ -659,7 +731,7 @@ func TestEncryptDecrypt(t *testing.T) {
if err != nil {
t.Fatal(err)
}
encTypes := []*EncrypterOpts{
encTypes := []EncrypterOpts{
DefaultEncrypterOpts, SM4ECBEncrypterOpts, SM4CBCEncrypterOpts, SM4CFBEncrypterOpts, SM4OFBEncrypterOpts,
}
for _, opts := range encTypes {
@ -699,7 +771,7 @@ func TestEncryptDecryptASN1(t *testing.T) {
if err != nil {
t.Fatal(err)
}
encTypes := []*EncrypterOpts{
encTypes := []EncrypterOpts{
DefaultEncrypterOpts, SM4ECBEncrypterOpts, SM4CBCEncrypterOpts, SM4CFBEncrypterOpts, SM4OFBEncrypterOpts,
}
for _, opts := range encTypes {