gmsm/sm9/sm9_key_test.go
YuanHongYe fe532e12b4 sm9: Prevent PublicKey() returning nil after unmarshaling master private key
During unmarshaling of SignMasterPrivateKey and EncryptMasterPrivateKey,
now generate the corresponding public key.
This ensures that PublicKey() does not return nil.

Test cases included to validate the changes.

Signed-off-by: YuanHongYe <yuanhongye@chinatelecom.cn>
2025-04-15 17:01:27 +08:00

325 lines
7.3 KiB
Go

package sm9
import (
"crypto/rand"
"encoding/hex"
"encoding/pem"
"testing"
"golang.org/x/crypto/cryptobyte"
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
)
func TestSignMasterPrivateKeyMarshalASN1(t *testing.T) {
masterKey, err := GenerateSignMasterKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := masterKey.MarshalASN1()
if err != nil {
t.Fatal(err)
}
masterKey2, err := UnmarshalSignMasterPrivateKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !masterKey.Equal(masterKey2) {
t.Errorf("expected %v, got %v", hex.EncodeToString(masterKey.Bytes()), hex.EncodeToString(masterKey2.Bytes()))
}
masterPubKey := masterKey2.PublicKey()
if masterPubKey == nil {
t.Fatal("cannot export public key")
}
}
func TestSignMasterPublicKeyMarshalASN1(t *testing.T) {
masterKey, err := GenerateSignMasterKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := masterKey.PublicKey().MarshalASN1()
if err != nil {
t.Fatal(err)
}
pub2, err := UnmarshalSignMasterPublicKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !pub2.Equal(masterKey.Public()) {
t.Errorf("not same")
}
}
func TestSignMasterPublicKeyMarshalCompressedASN1(t *testing.T) {
masterKey, err := GenerateSignMasterKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := masterKey.PublicKey().MarshalCompressedASN1()
if err != nil {
t.Fatal(err)
}
pub2, err := UnmarshalSignMasterPublicKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !pub2.Equal(masterKey.Public()) {
t.Errorf("not same")
}
}
func TestSignUserPrivateKeyMarshalASN1(t *testing.T) {
masterKey, err := GenerateSignMasterKey(rand.Reader)
uid := []byte("emmansun")
hid := byte(0x01)
if err != nil {
t.Fatal(err)
}
userKey, err := masterKey.GenerateUserKey(uid, hid)
if err != nil {
t.Fatal(err)
}
der, err := userKey.MarshalASN1()
if err != nil {
t.Fatal(err)
}
userKey2, err := UnmarshalSignPrivateKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !userKey.Equal(userKey2) {
t.Errorf("not same")
}
}
func TestSignUserPrivateKeyMarshalCompressedASN1(t *testing.T) {
masterKey, err := GenerateSignMasterKey(rand.Reader)
uid := []byte("emmansun")
hid := byte(0x01)
if err != nil {
t.Fatal(err)
}
userKey, err := masterKey.GenerateUserKey(uid, hid)
if err != nil {
t.Fatal(err)
}
der, err := userKey.MarshalCompressedASN1()
if err != nil {
t.Fatal(err)
}
userKey2, err := UnmarshalSignPrivateKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !userKey.Equal(userKey2) {
t.Errorf("not same")
}
}
func TestEncryptMasterPrivateKeyMarshalASN1(t *testing.T) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := masterKey.MarshalASN1()
if err != nil {
t.Fatal(err)
}
masterKey2, err := UnmarshalEncryptMasterPrivateKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !masterKey.Equal(masterKey2) {
t.Errorf("expected %v, got %v", hex.EncodeToString(masterKey.Bytes()), hex.EncodeToString(masterKey2.Bytes()))
}
masterPubKey := masterKey2.PublicKey()
if masterPubKey == nil {
t.Fatal("cannot export public key")
}
}
func TestEncryptMasterPublicKeyMarshalASN1(t *testing.T) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := masterKey.PublicKey().MarshalASN1()
if err != nil {
t.Fatal(err)
}
pub2, err := UnmarshalEncryptMasterPublicKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !pub2.Equal(masterKey.Public()) {
t.Errorf("not same")
}
}
func TestEncryptMasterPublicKeyMarshalCompressedASN1(t *testing.T) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
if err != nil {
t.Fatal(err)
}
der, err := masterKey.PublicKey().MarshalCompressedASN1()
if err != nil {
t.Fatal(err)
}
pub2, err := UnmarshalEncryptMasterPublicKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !pub2.Equal(masterKey.Public()) {
t.Errorf("not same")
}
}
func TestEncryptUserPrivateKeyMarshalASN1(t *testing.T) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
uid := []byte("emmansun")
hid := byte(0x01)
if err != nil {
t.Fatal(err)
}
userKey, err := masterKey.GenerateUserKey(uid, hid)
if err != nil {
t.Fatal(err)
}
der, err := userKey.MarshalASN1()
if err != nil {
t.Fatal(err)
}
userKey2, err := UnmarshalEncryptPrivateKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !userKey.Equal(userKey2) {
t.Errorf("not same")
}
}
func TestEncryptUserPrivateKeyMarshalCompressedASN1(t *testing.T) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
uid := []byte("emmansun")
hid := byte(0x01)
if err != nil {
t.Fatal(err)
}
userKey, err := masterKey.GenerateUserKey(uid, hid)
if err != nil {
t.Fatal(err)
}
der, err := userKey.MarshalCompressedASN1()
if err != nil {
t.Fatal(err)
}
userKey2, err := UnmarshalEncryptPrivateKeyASN1(der)
if err != nil {
t.Fatal(err)
}
if !userKey.Equal(userKey2) {
t.Errorf("not same")
}
}
func BenchmarkGenerateSignPrivKey(b *testing.B) {
masterKey, err := GenerateSignMasterKey(rand.Reader)
uid := []byte("emmansun")
hid := byte(0x01)
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := masterKey.GenerateUserKey(uid, hid); err != nil {
b.Fatal(err)
}
}
}
func BenchmarkGenerateEncryptPrivKey(b *testing.B) {
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
uid := []byte("emmansun")
hid := byte(0x01)
if err != nil {
b.Fatal(err)
}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := masterKey.GenerateUserKey(uid, hid); err != nil {
b.Fatal(err)
}
}
}
const sm9SignMasterPublicKeyFromGMSSL = `-----BEGIN SM9 SIGN MASTER PUBLIC KEY-----
MIGFA4GCAARvTUvk1ztAlmjlUK0kP3zdFEVHHr8HUL4sUbcnFoQPukP0AjurnySy
f1MY0Plzt4lZ5u0/6GC4zUjYEcjWiYV+bV9YCnOGVQAYfPr/a+4/alewf43qBJuX
Ri1gDhueE6gkoeZ4HHUu1wfhRbKRF8okwSO933f/ZSpLlYu1P7/ckw==
-----END SM9 SIGN MASTER PUBLIC KEY-----
`
func TestParseSM9SignMasterPublicKey(t *testing.T) {
key, err := ParseSignMasterPublicKeyPEM([]byte(sm9SignMasterPublicKeyFromGMSSL))
if err != nil {
t.Fatal(err)
}
// create sign master public key PEM with cryptobyte
var b cryptobyte.Builder
bytes, _ := key.MarshalASN1()
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddBytes(bytes)
})
data, err := b.Bytes()
if err != nil {
t.Fatal(err)
}
block := &pem.Block{Bytes: data, Type: "SM9 SIGN MASTER PUBLIC KEY"}
pemContent := string(pem.EncodeToMemory(block))
if pemContent != sm9SignMasterPublicKeyFromGMSSL {
t.Fatalf("failed %s\n", pemContent)
}
}
const sm9EncMasterPublicKeyFromGMSSL = `-----BEGIN SM9 ENC MASTER PUBLIC KEY-----
MEQDQgAEUWC+GS/3JrpMJqH/ZBItUDROFg62fmY4HuU0kHlnK/trA/GBX/P+MH0P
tYwoUdCETdYJwxiKXlI1jytVTuuT2Q==
-----END SM9 ENC MASTER PUBLIC KEY-----
`
func TestParseSM9EncryptMasterPublicKey(t *testing.T) {
key, err := ParseEncryptMasterPublicKeyPEM([]byte(sm9EncMasterPublicKeyFromGMSSL))
if err != nil {
t.Fatal(err)
}
// create encrypt master public key PEM with asn1
var b cryptobyte.Builder
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1BitString(key.Bytes())
})
data, err := b.Bytes()
if err != nil {
t.Fatal(err)
}
if err != nil {
t.Fatal(err)
}
block := &pem.Block{Bytes: data, Type: "SM9 ENC MASTER PUBLIC KEY"}
pemContent := string(pem.EncodeToMemory(block))
if pemContent != sm9EncMasterPublicKeyFromGMSSL {
t.Fatalf("failed %s\n", pemContent)
}
}