mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-27 04:36:19 +08:00
SM9: supplement comment and sample test case
This commit is contained in:
parent
14af2513d8
commit
3320de17b8
23
sm9/sm9.go
23
sm9/sm9.go
@ -16,6 +16,8 @@ import (
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
// SM9 ASN.1 format reference: Information security technology - SM9 cryptographic algorithm application specification
|
||||
|
||||
var bigOne = big.NewInt(1)
|
||||
|
||||
type hashMode byte
|
||||
@ -84,6 +86,7 @@ func randFieldElement(rand io.Reader) (k *big.Int, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// Pair generate the basepoint once
|
||||
func (pub *SignMasterPublicKey) Pair() *GT {
|
||||
pub.pairOnce.Do(func() {
|
||||
pub.basePoint = Pair(Gen1, pub.MasterPublicKey)
|
||||
@ -116,6 +119,7 @@ func (pub *SignMasterPublicKey) generatorTable() *[32 * 2]gtTable {
|
||||
return pub.table
|
||||
}
|
||||
|
||||
// ScalarBaseMult compute basepoint^r with precomputed table
|
||||
func (pub *SignMasterPublicKey) ScalarBaseMult(r *big.Int) *GT {
|
||||
scalar := normalizeScalar(r.Bytes())
|
||||
tables := pub.generatorTable()
|
||||
@ -176,6 +180,7 @@ func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *G1,
|
||||
|
||||
// Sign signs digest with user's DSA key, reading randomness from rand. The opts argument
|
||||
// is not currently used but, in keeping with the crypto.Signer interface.
|
||||
// The result is SM9Signature ASN.1 format.
|
||||
func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
h, s, err := Sign(rand, priv, hash)
|
||||
if err != nil {
|
||||
@ -194,7 +199,7 @@ func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.Signer
|
||||
}
|
||||
|
||||
// SignASN1 signs a hash (which should be the result of hashing a larger message)
|
||||
// using the private key, priv. It returns the ASN.1 encoded signature.
|
||||
// using the private key, priv. It returns the ASN.1 encoded signature of type SM9Signature.
|
||||
func SignASN1(rand io.Reader, priv *SignPrivateKey, hash []byte) ([]byte, error) {
|
||||
return priv.Sign(rand, hash, nil)
|
||||
}
|
||||
@ -225,7 +230,7 @@ func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big.
|
||||
return h.Cmp(h2) == 0
|
||||
}
|
||||
|
||||
// VerifyASN1 verifies the ASN.1 encoded signature, sig, of hash using the
|
||||
// VerifyASN1 verifies the ASN.1 encoded signature of type SM9Signature, sig, of hash using the
|
||||
// public key, pub. Its return value records whether the signature is valid.
|
||||
func VerifyASN1(pub *SignMasterPublicKey, uid []byte, hid byte, hash, sig []byte) bool {
|
||||
var (
|
||||
@ -260,6 +265,7 @@ func (pub *SignMasterPublicKey) Verify(uid []byte, hid byte, hash, sig []byte) b
|
||||
return VerifyASN1(pub, uid, hid, hash, sig)
|
||||
}
|
||||
|
||||
// Pair generate the basepoint once
|
||||
func (pub *EncryptMasterPublicKey) Pair() *GT {
|
||||
pub.pairOnce.Do(func() {
|
||||
pub.basePoint = Pair(pub.MasterPublicKey, Gen2)
|
||||
@ -292,6 +298,7 @@ func (pub *EncryptMasterPublicKey) generatorTable() *[32 * 2]gtTable {
|
||||
return pub.table
|
||||
}
|
||||
|
||||
// ScalarBaseMult compute basepoint^r with precomputed table
|
||||
func (pub *EncryptMasterPublicKey) ScalarBaseMult(r *big.Int) *GT {
|
||||
scalar := normalizeScalar(r.Bytes())
|
||||
tables := pub.generatorTable()
|
||||
@ -346,7 +353,7 @@ func WrapKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
|
||||
return
|
||||
}
|
||||
|
||||
// WrapKey wrap key and marshal the cipher as ASN1 format.
|
||||
// WrapKey wrap key and marshal 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 {
|
||||
@ -360,7 +367,7 @@ func (pub *EncryptMasterPublicKey) WrapKey(rand io.Reader, uid []byte, hid byte,
|
||||
}
|
||||
|
||||
// WrapKeyASN1 wrap key and marshal the result of SM9KeyPackage as ASN1 format. according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
// 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)
|
||||
if err != nil {
|
||||
@ -416,6 +423,8 @@ func UnwrapKey(priv *EncryptPrivateKey, uid []byte, cipher *G1, kLen int) ([]byt
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// UnwrapKey unwrap 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
|
||||
input := cryptobyte.String(cipherDer)
|
||||
@ -447,13 +456,13 @@ func Encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
|
||||
}
|
||||
|
||||
// EncryptASN1 encrypt plaintext and output ciphertext with ASN.1 format according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
|
||||
func EncryptASN1(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, plaintext []byte) ([]byte, error) {
|
||||
return pub.Encrypt(rand, uid, hid, plaintext)
|
||||
}
|
||||
|
||||
// Encrypt encrypt plaintext and output ciphertext with ASN.1 format according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
|
||||
func (pub *EncryptMasterPublicKey) Encrypt(rand io.Reader, uid []byte, hid byte, plaintext []byte) ([]byte, error) {
|
||||
key, cipher, err := WrapKey(rand, pub, uid, hid, len(plaintext)+sm3.Size)
|
||||
if err != nil {
|
||||
@ -504,7 +513,7 @@ func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error) {
|
||||
}
|
||||
|
||||
// DecryptASN1 decrypt chipher, ciphertext should be with ASN.1 format according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
// SM9 cryptographic algorithm application specification, SM9Cipher definition.
|
||||
func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error) {
|
||||
if len(ciphertext) <= 32+65 {
|
||||
return nil, errors.New("sm9: invalid ciphertext length")
|
||||
|
@ -9,40 +9,46 @@ import (
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
)
|
||||
|
||||
// SignMasterPrivateKey master private key for sign, generated by KGC
|
||||
type SignMasterPrivateKey struct {
|
||||
SignMasterPublicKey
|
||||
D *big.Int
|
||||
SignMasterPublicKey // master public key
|
||||
D *big.Int // master private key
|
||||
}
|
||||
|
||||
// SignMasterPublicKey master public key for sign, generated by KGC
|
||||
type SignMasterPublicKey struct {
|
||||
MasterPublicKey *G2
|
||||
MasterPublicKey *G2 // master public key
|
||||
pairOnce sync.Once
|
||||
basePoint *GT
|
||||
basePoint *GT // the result of Pair(Gen1, pub.MasterPublicKey)
|
||||
tableGenOnce sync.Once
|
||||
table *[32 * 2]gtTable
|
||||
table *[32 * 2]gtTable // precomputed basePoint^n
|
||||
}
|
||||
|
||||
// SignPrivateKey user private key for sign, generated by KGC
|
||||
type SignPrivateKey struct {
|
||||
PrivateKey *G1
|
||||
SignMasterPublicKey
|
||||
PrivateKey *G1 // user private key
|
||||
SignMasterPublicKey // master public key
|
||||
}
|
||||
|
||||
// EncryptMasterPrivateKey master private key for encryption, generated by KGC
|
||||
type EncryptMasterPrivateKey struct {
|
||||
EncryptMasterPublicKey
|
||||
D *big.Int
|
||||
EncryptMasterPublicKey // master public key
|
||||
D *big.Int // master private key
|
||||
}
|
||||
|
||||
// EncryptMasterPublicKey master private key for encryption, generated by KGC
|
||||
type EncryptMasterPublicKey struct {
|
||||
MasterPublicKey *G1
|
||||
MasterPublicKey *G1 // public key
|
||||
pairOnce sync.Once
|
||||
basePoint *GT
|
||||
basePoint *GT // the result of Pair(pub.MasterPublicKey, Gen2)
|
||||
tableGenOnce sync.Once
|
||||
table *[32 * 2]gtTable
|
||||
table *[32 * 2]gtTable // precomputed basePoint^n
|
||||
}
|
||||
|
||||
// EncryptPrivateKey user private key for encryption, generated by KGC
|
||||
type EncryptPrivateKey struct {
|
||||
PrivateKey *G2
|
||||
EncryptMasterPublicKey
|
||||
PrivateKey *G2 // user private key
|
||||
EncryptMasterPublicKey // master public key
|
||||
}
|
||||
|
||||
// GenerateSignMasterKey generates a master public and private key pair for DSA usage.
|
||||
|
@ -39,7 +39,9 @@ func TestSignMasterPublicKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if masterKey.MasterPublicKey.p.x != pub2.MasterPublicKey.p.x || masterKey.MasterPublicKey.p.y != pub2.MasterPublicKey.p.y || masterKey.MasterPublicKey.p.z != pub2.MasterPublicKey.p.z {
|
||||
if masterKey.MasterPublicKey.p.x != pub2.MasterPublicKey.p.x ||
|
||||
masterKey.MasterPublicKey.p.y != pub2.MasterPublicKey.p.y ||
|
||||
masterKey.MasterPublicKey.p.z != pub2.MasterPublicKey.p.z {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -64,7 +66,8 @@ func TestSignUserPrivateKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if userKey.PrivateKey.p.x != userKey2.PrivateKey.p.x || userKey.PrivateKey.p.y != userKey2.PrivateKey.p.y {
|
||||
if userKey.PrivateKey.p.x != userKey2.PrivateKey.p.x ||
|
||||
userKey.PrivateKey.p.y != userKey2.PrivateKey.p.y {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -102,7 +105,8 @@ func TestEncryptMasterPublicKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if masterKey.MasterPublicKey.p.x != pub2.MasterPublicKey.p.x || masterKey.MasterPublicKey.p.y != pub2.MasterPublicKey.p.y {
|
||||
if masterKey.MasterPublicKey.p.x != pub2.MasterPublicKey.p.x ||
|
||||
masterKey.MasterPublicKey.p.y != pub2.MasterPublicKey.p.y {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -127,7 +131,9 @@ func TestEncryptUserPrivateKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if userKey.PrivateKey.p.x != userKey2.PrivateKey.p.x || userKey.PrivateKey.p.y != userKey2.PrivateKey.p.y || userKey.PrivateKey.p.z != userKey2.PrivateKey.p.z {
|
||||
if userKey.PrivateKey.p.x != userKey2.PrivateKey.p.x ||
|
||||
userKey.PrivateKey.p.y != userKey2.PrivateKey.p.y ||
|
||||
userKey.PrivateKey.p.z != userKey2.PrivateKey.p.z {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
|
@ -78,6 +78,45 @@ func TestSignASN1(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix A
|
||||
func TestSignSM9Sample(t *testing.T) {
|
||||
expectedH := bigFromHex("823c4b21e4bd2dfe1ed92c606653e996668563152fc33f55d7bfbb9bd9705adb")
|
||||
expectedS := "0473bf96923ce58b6ad0e13e9643a406d8eb98417c50ef1b29cef9adb48b6d598c856712f1c2e0968ab7769f42a99586aed139d5b8b3e15891827cc2aced9baa05"
|
||||
hash := []byte("Chinese IBS standard")
|
||||
hid := byte(0x01)
|
||||
uid := []byte("Alice")
|
||||
r := bigFromHex("033c8616b06704813203dfd00965022ed15975c662337aed648835dc4b1cbe")
|
||||
masterKey := new(SignMasterPrivateKey)
|
||||
masterKey.D = bigFromHex("0130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4")
|
||||
masterKey.MasterPublicKey = new(G2).ScalarBaseMult(masterKey.D)
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w := userKey.SignMasterPublicKey.ScalarBaseMult(r)
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(buffer, hash...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
|
||||
h := hashH2(buffer)
|
||||
if h.Cmp(expectedH) != 0 {
|
||||
t.Fatal("not same h")
|
||||
}
|
||||
|
||||
l := new(big.Int).Sub(r, h)
|
||||
|
||||
if l.Sign() < 0 {
|
||||
l.Add(l, Order)
|
||||
}
|
||||
|
||||
s := new(G1).ScalarMult(userKey.PrivateKey, l)
|
||||
|
||||
if hex.EncodeToString(s.MarshalUncompressed()) != expectedS {
|
||||
t.Fatal("not same S")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapKey(t *testing.T) {
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
hid := byte(0x01)
|
||||
@ -161,6 +200,7 @@ func TestUnmarshalSM9KeyPackage(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix C
|
||||
func TestWrapKeySM9Sample(t *testing.T) {
|
||||
expectedKey := "4ff5cf86d2ad40c8f4bac98d76abdbde0c0e2f0a829d3f911ef5b2bce0695480"
|
||||
masterKey := new(EncryptMasterPrivateKey)
|
||||
@ -209,6 +249,7 @@ func TestWrapKeySM9Sample(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix D
|
||||
func TestEncryptSM9Sample(t *testing.T) {
|
||||
plaintext := []byte("Chinese IBE standard")
|
||||
expectedCiphertext := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0ba672387bcd6de5016a158a52bb2e7fc429197bcab70b25afee37a2b9db9f3671b5f5b0e951489682f3e64e1378cdd5da9513b1c"
|
||||
|
Loading…
x
Reference in New Issue
Block a user