mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-23 02:36:20 +08:00
862 lines
26 KiB
Go
862 lines
26 KiB
Go
package sm2
|
|
|
|
import (
|
|
"bufio"
|
|
"bytes"
|
|
"crypto"
|
|
"crypto/ecdsa"
|
|
"crypto/elliptic"
|
|
"crypto/rand"
|
|
"encoding/hex"
|
|
"io"
|
|
"math/big"
|
|
"reflect"
|
|
"testing"
|
|
|
|
"github.com/emmansun/gmsm/sm3"
|
|
)
|
|
|
|
func TestNewPrivateKey(t *testing.T) {
|
|
c := p256()
|
|
// test nil
|
|
_, err := NewPrivateKey(nil)
|
|
if err == nil || err.Error() != "sm2: invalid private key size" {
|
|
t.Errorf("should throw sm2: invalid private key size")
|
|
}
|
|
// test all zero
|
|
key := make([]byte, c.N.Size())
|
|
_, err = NewPrivateKey(key)
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("should throw errInvalidPrivateKey")
|
|
}
|
|
// test N-1
|
|
_, err = NewPrivateKey(c.nMinus1.Bytes(c.N))
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("should throw errInvalidPrivateKey")
|
|
}
|
|
// test N
|
|
_, err = NewPrivateKey(P256().Params().N.Bytes())
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("should throw errInvalidPrivateKey")
|
|
}
|
|
// test 1
|
|
key[31] = 1
|
|
_, err = NewPrivateKey(key)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// test N-2
|
|
_, err = NewPrivateKey(c.nMinus2)
|
|
if err != nil {
|
|
t.Error(err)
|
|
}
|
|
}
|
|
|
|
func TestNewPrivateKeyFromInt(t *testing.T) {
|
|
// test nil
|
|
_, err := NewPrivateKeyFromInt(nil)
|
|
if err == nil || err.Error() != "sm2: invalid private key size" {
|
|
t.Errorf("should throw sm2: invalid private key size")
|
|
}
|
|
// test 1
|
|
_, err = NewPrivateKeyFromInt(big.NewInt(1))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// test N
|
|
_, err = NewPrivateKeyFromInt(P256().Params().N)
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("should throw errInvalidPrivateKey")
|
|
}
|
|
|
|
// test N + 1
|
|
_, err = NewPrivateKeyFromInt(new(big.Int).Add(P256().Params().N, big.NewInt(1)))
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("should throw errInvalidPrivateKey")
|
|
}
|
|
|
|
c := p256()
|
|
// test N - 1
|
|
_, err = NewPrivateKeyFromInt(new(big.Int).SetBytes(c.nMinus1.Bytes(c.N)))
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("should throw errInvalidPrivateKey")
|
|
}
|
|
}
|
|
|
|
func TestNewPublicKey(t *testing.T) {
|
|
// test nil
|
|
_, err := NewPublicKey(nil)
|
|
if err == nil || err.Error() != "sm2: invalid public key" {
|
|
t.Errorf("should throw sm2: invalid public key")
|
|
}
|
|
// test without point format prefix byte
|
|
keypoints, _ := hex.DecodeString("8356e642a40ebd18d29ba3532fbd9f3bbee8f027c3f6f39a5ba2f870369f9988981f5efe55d1c5cdf6c0ef2b070847a14f7fdf4272a8df09c442f3058af94ba1")
|
|
_, err = NewPublicKey(keypoints)
|
|
if err == nil || err.Error() != "sm2: invalid public key" {
|
|
t.Errorf("should throw sm2: invalid public key")
|
|
}
|
|
// test correct point
|
|
keypoints, _ = hex.DecodeString("048356e642a40ebd18d29ba3532fbd9f3bbee8f027c3f6f39a5ba2f870369f9988981f5efe55d1c5cdf6c0ef2b070847a14f7fdf4272a8df09c442f3058af94ba1")
|
|
_, err = NewPublicKey(keypoints)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
// test point not on curve
|
|
keypoints, _ = hex.DecodeString("048356e642a40ebd18d29ba3532fbd9f3bbee8f027c3f6f39a5ba2f870369f9988981f5efe55d1c5cdf6c0ef2b070847a14f7fdf4272a8df09c442f3058af94ba2")
|
|
_, err = NewPublicKey(keypoints)
|
|
if err == nil || err.Error() != "point not on SM2 P256 curve" {
|
|
t.Errorf("should throw point not on SM2 P256 curve, got %v", err)
|
|
}
|
|
}
|
|
|
|
func TestSplicingOrder(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
from ciphertextSplicingOrder
|
|
to ciphertextSplicingOrder
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32 1", "encryption standard", C1C2C3, C1C3C2},
|
|
{"less than 32 2", "encryption standard", C1C3C2, C1C2C3},
|
|
{"equals 32 1", "encryption standard encryption ", C1C2C3, C1C3C2},
|
|
{"equals 32 2", "encryption standard encryption ", C1C3C2, C1C2C3},
|
|
{"long than 32 1", "encryption standard encryption standard", C1C2C3, C1C3C2},
|
|
{"long than 32 2", "encryption standard encryption standard", C1C3C2, C1C2C3},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), NewPlainEncrypterOpts(MarshalUncompressed, tt.from))
|
|
if err != nil {
|
|
t.Fatalf("encrypt failed %v", err)
|
|
}
|
|
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, NewPlainDecrypterOpts(tt.from))
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
|
|
//Adjust splicing order
|
|
ciphertext, err = AdjustCiphertextSplicingOrder(ciphertext, tt.from, tt.to)
|
|
if err != nil {
|
|
t.Fatalf("adjust splicing order failed %v", err)
|
|
}
|
|
plaintext, err = priv.Decrypt(rand.Reader, ciphertext, NewPlainDecrypterOpts(tt.to))
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed after adjust splicing order %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEncryptDecryptASN1(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
priv2, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
key2 := new(PrivateKey)
|
|
key2.PrivateKey = *priv2
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
priv *PrivateKey
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32", "encryption standard", priv},
|
|
{"equals 32", "encryption standard encryption ", priv},
|
|
{"long than 32", "encryption standard encryption standard", priv},
|
|
{"less than 32", "encryption standard", key2},
|
|
{"equals 32", "encryption standard encryption ", key2},
|
|
{"long than 32", "encryption standard encryption standard", key2},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
encrypterOpts := ASN1EncrypterOpts
|
|
ciphertext, err := Encrypt(rand.Reader, &tt.priv.PublicKey, []byte(tt.plainText), encrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("%v encrypt failed %v", tt.priv.Curve.Params().Name, err)
|
|
}
|
|
plaintext, err := tt.priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("%v decrypt 1 failed %v", tt.priv.Curve.Params().Name, err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
plaintext, err = tt.priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("%v decrypt 2 failed %v", tt.priv.Curve.Params().Name, err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestPlainCiphertext2ASN1(t *testing.T) {
|
|
ciphertext, _ := hex.DecodeString("047928e22045eec8dc00e95639dd0c1c8dfb75cf8cedcf496731a6a6f423baa54c5014c60b73495886d8d7bc996a4a716cb58e6bfc8e03078b24e7b0f5cba0efd5b9272c27fc263bb59eaca6eabc97c0323bf1de953aeabaf59700b3bf49c9a1056decc08dd18544960541a2239afa7b1512df05")
|
|
_, err := PlainCiphertext2ASN1(append([]byte{0x30}, ciphertext...), C1C3C2)
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
_, err = PlainCiphertext2ASN1(ciphertext[:65], C1C3C2)
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
ciphertext[0] = 0x10
|
|
_, err = PlainCiphertext2ASN1(ciphertext, C1C3C2)
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
}
|
|
|
|
func TestAdjustCiphertextSplicingOrder(t *testing.T) {
|
|
ciphertext, _ := hex.DecodeString("047928e22045eec8dc00e95639dd0c1c8dfb75cf8cedcf496731a6a6f423baa54c5014c60b73495886d8d7bc996a4a716cb58e6bfc8e03078b24e7b0f5cba0efd5b9272c27fc263bb59eaca6eabc97c0323bf1de953aeabaf59700b3bf49c9a1056decc08dd18544960541a2239afa7b1512df05")
|
|
res, err := AdjustCiphertextSplicingOrder(ciphertext, C1C3C2, C1C3C2)
|
|
if err != nil || &res[0] != &ciphertext[0] {
|
|
t.Fatalf("should be same one")
|
|
}
|
|
_, err = AdjustCiphertextSplicingOrder(ciphertext[:65], C1C3C2, C1C2C3)
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
ciphertext[0] = 0x10
|
|
_, err = AdjustCiphertextSplicingOrder(ciphertext, C1C3C2, C1C2C3)
|
|
if err == nil {
|
|
t.Fatalf("expected error")
|
|
}
|
|
}
|
|
|
|
func TestCiphertext2ASN1(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32", "encryption standard"},
|
|
{"equals 32", "encryption standard encryption "},
|
|
{"long than 32", "encryption standard encryption standard"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ciphertext1, err := Encrypt(rand.Reader, &priv.PublicKey, []byte(tt.plainText), nil)
|
|
if err != nil {
|
|
t.Fatalf("encrypt failed %v", err)
|
|
}
|
|
|
|
ciphertext, err := PlainCiphertext2ASN1(ciphertext1, C1C3C2)
|
|
if err != nil {
|
|
t.Fatalf("convert to ASN.1 failed %v", err)
|
|
}
|
|
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
|
|
ciphertext2, err := AdjustCiphertextSplicingOrder(ciphertext1, C1C3C2, C1C2C3)
|
|
if err != nil {
|
|
t.Fatalf("adjust order failed %v", err)
|
|
}
|
|
ciphertext, err = PlainCiphertext2ASN1(ciphertext2, C1C2C3)
|
|
if err != nil {
|
|
t.Fatalf("convert to ASN.1 failed %v", err)
|
|
}
|
|
plaintext, err = priv.Decrypt(rand.Reader, ciphertext, ASN1DecrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestCiphertextASN12Plain(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32", "encryption standard"},
|
|
{"equals 32", "encryption standard encryption "},
|
|
{"long than 32", "encryption standard encryption standard"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ciphertext, err := EncryptASN1(rand.Reader, &priv.PublicKey, []byte(tt.plainText))
|
|
if err != nil {
|
|
t.Fatalf("encrypt failed %v", err)
|
|
}
|
|
ciphertext, err = ASN1Ciphertext2Plain(ciphertext, nil)
|
|
if err != nil {
|
|
t.Fatalf("convert to plain failed %v", err)
|
|
}
|
|
plaintext, err := priv.Decrypt(rand.Reader, ciphertext, nil)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestEncryptWithInfinitePublicKey(t *testing.T) {
|
|
pub := new(ecdsa.PublicKey)
|
|
pub.Curve = P256()
|
|
pub.X = big.NewInt(0)
|
|
pub.Y = big.NewInt(0)
|
|
|
|
_, err := Encrypt(rand.Reader, pub, []byte("sm2 encryption standard"), nil)
|
|
if err == nil {
|
|
t.Fatalf("should be failed")
|
|
}
|
|
}
|
|
|
|
func TestEncryptEmptyPlaintext(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
ciphertext, err := Encrypt(rand.Reader, &priv.PublicKey, nil, nil)
|
|
if err != nil || ciphertext != nil {
|
|
t.Fatalf("nil plaintext should return nil")
|
|
}
|
|
ciphertext, err = Encrypt(rand.Reader, &priv.PublicKey, []byte{}, nil)
|
|
if err != nil || ciphertext != nil {
|
|
t.Fatalf("empty plaintext should return nil")
|
|
}
|
|
}
|
|
|
|
func TestEncryptDecrypt(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
priv2, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
key2 := new(PrivateKey)
|
|
key2.PrivateKey = *priv2
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
priv *PrivateKey
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32", "encryption standard", priv},
|
|
{"equals 32", "encryption standard encryption ", priv},
|
|
{"long than 32", "encryption standard encryption standard", priv},
|
|
{"less than 32", "encryption standard", key2},
|
|
{"equals 32", "encryption standard encryption ", key2},
|
|
{"long than 32", "encryption standard encryption standard", key2},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
ciphertext, err := Encrypt(rand.Reader, &tt.priv.PublicKey, []byte(tt.plainText), nil)
|
|
if err != nil {
|
|
t.Fatalf("encrypt failed %v", err)
|
|
}
|
|
plaintext, err := Decrypt(tt.priv, ciphertext)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
// compress mode
|
|
encrypterOpts := NewPlainEncrypterOpts(MarshalCompressed, C1C3C2)
|
|
ciphertext, err = Encrypt(rand.Reader, &tt.priv.PublicKey, []byte(tt.plainText), encrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("encrypt failed %v", err)
|
|
}
|
|
plaintext, err = Decrypt(tt.priv, ciphertext)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
|
|
// hybrid mode
|
|
encrypterOpts = NewPlainEncrypterOpts(MarshalHybrid, C1C3C2)
|
|
ciphertext, err = Encrypt(rand.Reader, &tt.priv.PublicKey, []byte(tt.plainText), encrypterOpts)
|
|
if err != nil {
|
|
t.Fatalf("encrypt failed %v", err)
|
|
}
|
|
plaintext, err = Decrypt(tt.priv, ciphertext)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
plaintext, err = Decrypt(tt.priv, ciphertext)
|
|
if err != nil {
|
|
t.Fatalf("decrypt failed %v", err)
|
|
}
|
|
if !reflect.DeepEqual(string(plaintext), tt.plainText) {
|
|
t.Errorf("Decrypt() = %v, want %v", string(plaintext), tt.plainText)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestInvalidCiphertext(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
tests := []struct {
|
|
name string
|
|
ciphertext []byte
|
|
}{
|
|
// TODO: Add test cases.
|
|
{errCiphertextTooShort.Error(), make([]byte, 65)},
|
|
{ErrDecryption.Error(), append([]byte{0x04}, make([]byte, 96)...)},
|
|
{ErrDecryption.Error(), append([]byte{0x04}, make([]byte, 97)...)},
|
|
{ErrDecryption.Error(), append([]byte{0x02}, make([]byte, 65)...)},
|
|
{ErrDecryption.Error(), append([]byte{0x30}, make([]byte, 97)...)},
|
|
{ErrDecryption.Error(), make([]byte, 97)},
|
|
}
|
|
for i, tt := range tests {
|
|
_, err := Decrypt(priv, tt.ciphertext)
|
|
if err.Error() != tt.name {
|
|
t.Fatalf("case %v, expected %v, got %v\n", i, tt.name, err.Error())
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestPrivateKeyPlus1WithOrderMinus1(t *testing.T) {
|
|
priv := new(PrivateKey)
|
|
priv.D = new(big.Int).Sub(P256().Params().N, big.NewInt(1))
|
|
priv.Curve = P256()
|
|
priv.PublicKey.X, priv.PublicKey.Y = P256().ScalarBaseMult(priv.D.Bytes())
|
|
|
|
_, err := priv.inverseOfPrivateKeyPlus1(p256())
|
|
if err == nil || err != errInvalidPrivateKey {
|
|
t.Errorf("expected invalid private key error")
|
|
}
|
|
}
|
|
|
|
func TestSignVerify(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32", "encryption standard"},
|
|
{"equals 32", "encryption standard encryption "},
|
|
{"long than 32", "encryption standard encryption standard"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
hashed := sm3.Sum([]byte(tt.plainText))
|
|
signature, err := priv.Sign(rand.Reader, hashed[:], nil)
|
|
if err != nil {
|
|
t.Fatalf("sign failed %v", err)
|
|
}
|
|
result := VerifyASN1(&priv.PublicKey, hashed[:], signature)
|
|
if !result {
|
|
t.Fatal("verify failed")
|
|
}
|
|
hashed[0] ^= 0xff
|
|
if VerifyASN1(&priv.PublicKey, hashed[:], signature) {
|
|
t.Errorf("VerifyASN1 always works!")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSignVerifyLegacy(t *testing.T) {
|
|
priv, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
tests := []struct {
|
|
name string
|
|
plainText string
|
|
}{
|
|
// TODO: Add test cases.
|
|
{"less than 32", "encryption standard"},
|
|
{"equals 32", "encryption standard encryption "},
|
|
{"long than 32", "encryption standard encryption standard"},
|
|
}
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
hashed := sm3.Sum([]byte(tt.plainText))
|
|
r, s, err := Sign(rand.Reader, priv, hashed[:])
|
|
if err != nil {
|
|
t.Fatalf("sign failed %v", err)
|
|
}
|
|
result := Verify(&priv.PublicKey, hashed[:], r, s)
|
|
if !result {
|
|
t.Fatal("verify failed")
|
|
}
|
|
hashed[0] ^= 0xff
|
|
if Verify(&priv.PublicKey, hashed[:], r, s) {
|
|
t.Errorf("VerifyASN1 always works!")
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
// Check that signatures remain non-deterministic with a functional entropy source.
|
|
func TestINDCCA(t *testing.T) {
|
|
priv, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
t.Errorf("failed to generate key")
|
|
}
|
|
|
|
hashed := []byte("testing")
|
|
r0, s0, err := Sign(rand.Reader, &priv.PrivateKey, hashed)
|
|
if err != nil {
|
|
t.Errorf("SM2: error signing: %s", err)
|
|
return
|
|
}
|
|
|
|
r1, s1, err := Sign(rand.Reader, &priv.PrivateKey, hashed)
|
|
if err != nil {
|
|
t.Errorf("SM2: error signing: %s", err)
|
|
return
|
|
}
|
|
|
|
if s0.Cmp(s1) == 0 {
|
|
t.Error("SM2: two signatures of the same message produced the same result")
|
|
}
|
|
|
|
if r0.Cmp(r1) == 0 {
|
|
t.Error("SM2: two signatures of the same message produced the same nonce")
|
|
}
|
|
}
|
|
|
|
func TestNegativeInputs(t *testing.T) {
|
|
key, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
t.Errorf("failed to generate key")
|
|
}
|
|
|
|
var hash [32]byte
|
|
r := new(big.Int).SetInt64(1)
|
|
r.Lsh(r, 550 /* larger than any supported curve */)
|
|
r.Neg(r)
|
|
|
|
if Verify(&key.PublicKey, hash[:], r, r) {
|
|
t.Errorf("bogus signature accepted")
|
|
}
|
|
}
|
|
|
|
func TestZeroHashSignature(t *testing.T) {
|
|
zeroHash := make([]byte, 64)
|
|
|
|
privKey, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Sign a hash consisting of all zeros.
|
|
r, s, err := Sign(rand.Reader, &privKey.PrivateKey, zeroHash)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
// Confirm that it can be verified.
|
|
if !Verify(&privKey.PublicKey, zeroHash, r, s) {
|
|
t.Errorf("zero hash signature verify failed")
|
|
}
|
|
}
|
|
|
|
func TestZeroSignature(t *testing.T) {
|
|
privKey, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
if Verify(&privKey.PublicKey, make([]byte, 64), big.NewInt(0), big.NewInt(0)) {
|
|
t.Error("Verify with r,s=0 succeeded")
|
|
}
|
|
}
|
|
|
|
func TestNegtativeSignature(t *testing.T) {
|
|
zeroHash := make([]byte, 64)
|
|
|
|
privKey, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
r, s, err := Sign(rand.Reader, &privKey.PrivateKey, zeroHash)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
r = r.Neg(r)
|
|
if Verify(&privKey.PublicKey, zeroHash, r, s) {
|
|
t.Error("Verify with r=-r succeeded")
|
|
}
|
|
}
|
|
|
|
func TestRPlusNSignature(t *testing.T) {
|
|
zeroHash := make([]byte, 64)
|
|
|
|
privKey, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
r, s, err := Sign(rand.Reader, &privKey.PrivateKey, zeroHash)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
r = r.Add(r, P256().Params().N)
|
|
if Verify(&privKey.PublicKey, zeroHash, r, s) {
|
|
t.Error("Verify with r=r+n succeeded")
|
|
}
|
|
}
|
|
|
|
func TestRMinusNSignature(t *testing.T) {
|
|
zeroHash := make([]byte, 64)
|
|
|
|
privKey, err := GenerateKey(rand.Reader)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
r, s, err := Sign(rand.Reader, &privKey.PrivateKey, zeroHash)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
|
|
r = r.Sub(r, P256().Params().N)
|
|
if Verify(&privKey.PublicKey, zeroHash, r, s) {
|
|
t.Error("Verify with r=r-n succeeded")
|
|
}
|
|
}
|
|
|
|
func TestEqual(t *testing.T) {
|
|
private, _ := GenerateKey(rand.Reader)
|
|
public := &private.PublicKey
|
|
|
|
if !public.Equal(public) {
|
|
t.Errorf("public key is not equal to itself: %q", public)
|
|
}
|
|
if !public.Equal(crypto.Signer(private).Public()) {
|
|
t.Errorf("private.Public() is not Equal to public: %q", public)
|
|
}
|
|
if !private.Equal(private) {
|
|
t.Errorf("private key is not equal to itself: %q", private.PrivateKey)
|
|
}
|
|
|
|
otherPriv, _ := GenerateKey(rand.Reader)
|
|
otherPub := &otherPriv.PublicKey
|
|
if public.Equal(otherPub) {
|
|
t.Errorf("different public keys are Equal")
|
|
}
|
|
if private.Equal(otherPriv) {
|
|
t.Errorf("different private keys are Equal")
|
|
}
|
|
}
|
|
|
|
func TestPublicKeyToECDH(t *testing.T) {
|
|
priv, _ := GenerateKey(rand.Reader)
|
|
_, err := PublicKeyToECDH(&priv.PublicKey)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
p256, _ := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
|
_, err = PublicKeyToECDH(&p256.PublicKey)
|
|
if err == nil {
|
|
t.Fatal("should be error")
|
|
}
|
|
}
|
|
|
|
func TestRandomPoint(t *testing.T) {
|
|
c := p256()
|
|
t.Cleanup(func() { testingOnlyRejectionSamplingLooped = nil })
|
|
var loopCount int
|
|
testingOnlyRejectionSamplingLooped = func() { loopCount++ }
|
|
|
|
// A sequence of all ones will generate 2^N-1, which should be rejected.
|
|
// (Unless, for example, we are masking too many bits.)
|
|
r := io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0xff}, 100)), rand.Reader)
|
|
if k, p, err := randomPoint(c, r, false); err != nil {
|
|
t.Fatal(err)
|
|
} else if k.IsZero() == 1 {
|
|
t.Error("k is zero")
|
|
} else if p.Bytes()[0] != 4 {
|
|
t.Error("p is infinity")
|
|
}
|
|
if loopCount == 0 {
|
|
t.Error("overflow was not rejected")
|
|
}
|
|
loopCount = 0
|
|
|
|
// A sequence of all zeroes will generate zero, which should be rejected.
|
|
r = io.MultiReader(bytes.NewReader(bytes.Repeat([]byte{0}, 100)), rand.Reader)
|
|
if k, p, err := randomPoint(c, r, false); err != nil {
|
|
t.Fatal(err)
|
|
} else if k.IsZero() == 1 {
|
|
t.Error("k is zero")
|
|
} else if p.Bytes()[0] != 4 {
|
|
t.Error("p is infinity")
|
|
}
|
|
if loopCount == 0 {
|
|
t.Error("zero was not rejected")
|
|
}
|
|
}
|
|
|
|
func BenchmarkGenerateKey_SM2(b *testing.B) {
|
|
r := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := GenerateKey(r); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkGenerateKey_P256(b *testing.B) {
|
|
r := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if _, err := ecdsa.GenerateKey(elliptic.P256(), r); err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkSign_SM2(b *testing.B) {
|
|
r := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
priv, err := GenerateKey(r)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
hashed := sm3.Sum([]byte("testing"))
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
sig, err := SignASN1(rand.Reader, priv, hashed[:], nil)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
// Prevent the compiler from optimizing out the operation.
|
|
hashed[0] = sig[0]
|
|
}
|
|
}
|
|
|
|
func BenchmarkSign_SM2Specific(b *testing.B) {
|
|
r := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
priv, err := GenerateKey(r)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
hashed := []byte("testingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtestingtesting")
|
|
b.RunParallel(func(p *testing.PB) {
|
|
for p.Next() {
|
|
_, err := priv.SignWithSM2(rand.Reader, nil, hashed)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func BenchmarkSign_P256(b *testing.B) {
|
|
r := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
priv, err := ecdsa.GenerateKey(elliptic.P256(), r)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
hashed := []byte("testing")
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
sig, err := ecdsa.SignASN1(rand.Reader, priv, hashed)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
// Prevent the compiler from optimizing out the operation.
|
|
hashed[0] = sig[0]
|
|
}
|
|
}
|
|
|
|
func BenchmarkVerify_P256(b *testing.B) {
|
|
rd := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
priv, err := ecdsa.GenerateKey(elliptic.P256(), rd)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
hashed := []byte("testing")
|
|
r, s, err := ecdsa.Sign(rand.Reader, priv, hashed)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if !ecdsa.Verify(&priv.PublicKey, hashed, r, s) {
|
|
b.Fatal("verify failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkVerify_SM2(b *testing.B) {
|
|
rd := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
priv, err := GenerateKey(rd)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
hashed := []byte("testing")
|
|
r, s, err := Sign(rand.Reader, &priv.PrivateKey, hashed)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
if !Verify(&priv.PublicKey, hashed, r, s) {
|
|
b.Fatal("verify failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func benchmarkEncrypt(b *testing.B, curve elliptic.Curve, plaintext string) {
|
|
r := bufio.NewReaderSize(rand.Reader, 1<<15)
|
|
priv, err := ecdsa.GenerateKey(curve, r)
|
|
if err != nil {
|
|
b.Fatal(err)
|
|
}
|
|
b.ReportAllocs()
|
|
b.ResetTimer()
|
|
for i := 0; i < b.N; i++ {
|
|
Encrypt(rand.Reader, &priv.PublicKey, []byte(plaintext), nil)
|
|
}
|
|
}
|
|
|
|
func BenchmarkLessThan32_P256(b *testing.B) {
|
|
benchmarkEncrypt(b, elliptic.P256(), "encryption standard")
|
|
}
|
|
|
|
func BenchmarkLessThan32_SM2(b *testing.B) {
|
|
benchmarkEncrypt(b, P256(), "encryption standard")
|
|
}
|
|
|
|
func BenchmarkMoreThan32_P256(b *testing.B) {
|
|
benchmarkEncrypt(b, elliptic.P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard")
|
|
}
|
|
|
|
func BenchmarkMoreThan32_SM2(b *testing.B) {
|
|
benchmarkEncrypt(b, P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard")
|
|
}
|
|
|
|
func BenchmarkEncrypt512_SM2(b *testing.B) {
|
|
benchmarkEncrypt(b, P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption s")
|
|
}
|
|
|
|
func BenchmarkEncrypt1024_SM2(b *testing.B) {
|
|
benchmarkEncrypt(b, P256(), "encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption sencryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption standard encryption s")
|
|
}
|