mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 20:26:19 +08:00
sm9: refactoring, do not expose bn256 types to caller #314
This commit is contained in:
parent
e9692d23ab
commit
43ffd49e2f
@ -1,5 +1,7 @@
|
||||
package bn256
|
||||
|
||||
import "math/big"
|
||||
|
||||
// u is the BN parameter that determines the prime: 600000000058f98a.
|
||||
var u = bigFromHex("600000000058f98a")
|
||||
|
||||
@ -17,8 +19,29 @@ var sixU2Plus1 = bigFromHex("d8000000019062ed0000b98b0cb27659")
|
||||
// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
|
||||
var p = bigFromHex("b640000002a3a6f1d603ab4ff58ec74521f2934b1a7aeedbe56f9b27e351457d")
|
||||
|
||||
var OrderBytes = []byte{
|
||||
0xb6, 0x40, 0x00, 0x00, 0x02, 0xa3, 0xa6, 0xf1,
|
||||
0xd6, 0x03, 0xab, 0x4f, 0xf5, 0x8e, 0xc7, 0x44,
|
||||
0x49, 0xf2, 0x93, 0x4b, 0x18, 0xea, 0x8b, 0xee,
|
||||
0xe5, 0x6e, 0xe1, 0x9c, 0xd6, 0x9e, 0xcf, 0x25,
|
||||
}
|
||||
|
||||
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
|
||||
var Order = bigFromHex("b640000002a3a6f1d603ab4ff58ec74449f2934b18ea8beee56ee19cd69ecf25")
|
||||
var Order = new(big.Int).SetBytes(OrderBytes)
|
||||
|
||||
var OrderMinus1Bytes = []byte{
|
||||
0xb6, 0x40, 0x00, 0x00, 0x02, 0xa3, 0xa6, 0xf1,
|
||||
0xd6, 0x03, 0xab, 0x4f, 0xf5, 0x8e, 0xc7, 0x44,
|
||||
0x49, 0xf2, 0x93, 0x4b, 0x18, 0xea, 0x8b, 0xee,
|
||||
0xe5, 0x6e, 0xe1, 0x9c, 0xd6, 0x9e, 0xcf, 0x24,
|
||||
}
|
||||
|
||||
var OrderMinus2Bytes = []byte{
|
||||
0xb6, 0x40, 0x00, 0x00, 0x02, 0xa3, 0xa6, 0xf1,
|
||||
0xd6, 0x03, 0xab, 0x4f, 0xf5, 0x8e, 0xc7, 0x44,
|
||||
0x49, 0xf2, 0x93, 0x4b, 0x18, 0xea, 0x8b, 0xee,
|
||||
0xe5, 0x6e, 0xe1, 0x9c, 0xd6, 0x9e, 0xcf, 0x23,
|
||||
}
|
||||
|
||||
// p2 is p, represented as little-endian 64-bit words.
|
||||
var p2 = [4]uint64{0xe56f9b27e351457d, 0x21f2934b1a7aeedb, 0xd603ab4ff58ec745, 0xb640000002a3a6f1}
|
454
internal/sm9/sm9.go
Normal file
454
internal/sm9/sm9.go
Normal file
@ -0,0 +1,454 @@
|
||||
// Package sm9 implements ShangMi(SM) sm9 digital signature, encryption and key exchange algorithms.
|
||||
package sm9
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
goSubtle "crypto/subtle"
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/bigmod"
|
||||
"github.com/emmansun/gmsm/internal/byteorder"
|
||||
"github.com/emmansun/gmsm/internal/randutil"
|
||||
"github.com/emmansun/gmsm/internal/sm3"
|
||||
"github.com/emmansun/gmsm/internal/sm9/bn256"
|
||||
"github.com/emmansun/gmsm/internal/subtle"
|
||||
)
|
||||
|
||||
// SM9 ASN.1 format reference: Information security technology - SM9 cryptographic algorithm application specification
|
||||
var (
|
||||
orderNat *bigmod.Modulus
|
||||
)
|
||||
|
||||
func init() {
|
||||
orderNat, _ = bigmod.NewModulus(bn256.OrderBytes)
|
||||
}
|
||||
|
||||
type hashMode byte
|
||||
|
||||
const (
|
||||
// hashmode used in h1: 0x01
|
||||
H1 hashMode = 1 + iota
|
||||
// hashmode used in h2: 0x02
|
||||
H2
|
||||
)
|
||||
|
||||
// hash implements H1(Z,n) or H2(Z,n) in sm9 algorithm.
|
||||
func hash(z []byte, h hashMode) *bigmod.Nat {
|
||||
md := sm3.New()
|
||||
var ha [64]byte
|
||||
var countBytes [4]byte
|
||||
var ct uint32 = 1
|
||||
|
||||
byteorder.BEPutUint32(countBytes[:], ct)
|
||||
md.Write([]byte{byte(h)})
|
||||
md.Write(z)
|
||||
md.Write(countBytes[:])
|
||||
copy(ha[:], md.Sum(nil))
|
||||
ct++
|
||||
md.Reset()
|
||||
|
||||
byteorder.BEPutUint32(countBytes[:], ct)
|
||||
md.Write([]byte{byte(h)})
|
||||
md.Write(z)
|
||||
md.Write(countBytes[:])
|
||||
copy(ha[sm3.Size:], md.Sum(nil))
|
||||
|
||||
return bigmod.NewNat().SetOverflowedBytes(ha[:40], orderNat)
|
||||
}
|
||||
|
||||
func hashH1(z []byte) *bigmod.Nat {
|
||||
return hash(z, H1)
|
||||
}
|
||||
|
||||
func hashH2(z []byte) *bigmod.Nat {
|
||||
return hash(z, H2)
|
||||
}
|
||||
|
||||
func randomScalar(rand io.Reader) (k *bigmod.Nat, err error) {
|
||||
k = bigmod.NewNat()
|
||||
for {
|
||||
b := make([]byte, orderNat.Size())
|
||||
if _, err = io.ReadFull(rand, b); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Mask off any excess bits to increase the chance of hitting a value in
|
||||
// (0, N). These are the most dangerous lines in the package and maybe in
|
||||
// the library: a single bit of bias in the selection of nonces would likely
|
||||
// lead to key recovery, but no tests would fail. Look but DO NOT TOUCH.
|
||||
if excess := len(b)*8 - orderNat.BitLen(); excess > 0 {
|
||||
// Just to be safe, assert that this only happens for the one curve that
|
||||
// doesn't have a round number of bits.
|
||||
if excess != 0 {
|
||||
panic("sm9: internal error: unexpectedly masking off bits")
|
||||
}
|
||||
b[0] >>= excess
|
||||
}
|
||||
|
||||
// FIPS 186-4 makes us check k <= N - 2 and then add one.
|
||||
// Checking 0 < k <= N - 1 is strictly equivalent.
|
||||
// None of this matters anyway because the chance of selecting
|
||||
// zero is cryptographically negligible.
|
||||
if _, err = k.SetBytes(b, orderNat); err == nil && k.IsZero() == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// 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 signature is randomized. Most applications should use [crypto/rand.Reader]
|
||||
// as rand. Note that the returned signature does not depend deterministically on
|
||||
// the bytes read from rand, and may change between calls and/or between versions.
|
||||
func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.SignerOpts) ([]byte, []byte, error) {
|
||||
var (
|
||||
hNat *bigmod.Nat
|
||||
s *bn256.G1
|
||||
)
|
||||
randutil.MaybeReadByte(rand)
|
||||
for {
|
||||
r, err := randomScalar(rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
w, err := priv.SignMasterPublicKey.ScalarBaseMult(r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, hash...), w.Marshal()...)
|
||||
|
||||
hNat = hashH2(buffer)
|
||||
r.Sub(hNat, orderNat)
|
||||
|
||||
if r.IsZero() == 0 {
|
||||
s, err = new(bn256.G1).ScalarMult(priv.PrivateKey, r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return hNat.Bytes(orderNat), s.MarshalUncompressed(), nil
|
||||
}
|
||||
|
||||
// Verify checks the validity of a signature using the provided parameters.
|
||||
func (pub *SignMasterPublicKey) Verify(uid []byte, hid byte, hash, h, s []byte) bool {
|
||||
sPoint := new(bn256.G1)
|
||||
_, err := sPoint.Unmarshal(s[1:])
|
||||
if err != nil || !sPoint.IsOnCurve() {
|
||||
return false
|
||||
}
|
||||
hNat, err := bigmod.NewNat().SetBytes(h, orderNat)
|
||||
if err != nil || hNat.IsZero() == 1 {
|
||||
return false
|
||||
}
|
||||
t, err := pub.ScalarBaseMult(hNat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// user sign public key p generation
|
||||
p := pub.GenerateUserPublicKey(uid, hid)
|
||||
|
||||
u := bn256.Pair(sPoint, p)
|
||||
w := new(bn256.GT).Add(u, t)
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, hash...), w.Marshal()...)
|
||||
h2 := hashH2(buffer)
|
||||
|
||||
return h2.Equal(hNat) == 1
|
||||
}
|
||||
|
||||
// WrapKey generates a wrapped key and its corresponding ciphertext.
|
||||
//
|
||||
// Parameters:
|
||||
// - rand: an io.Reader used to generate random values.
|
||||
// - uid: a byte slice representing the user ID.
|
||||
// - hid: a byte representing the hash ID.
|
||||
// - kLen: an integer specifying the desired key length.
|
||||
//
|
||||
// Returns:
|
||||
// - A byte slice containing the generated key.
|
||||
// - A byte slice containing the uncompressed ciphertext.
|
||||
// - An error if any occurs during the key wrapping process.
|
||||
func (pub *EncryptMasterPublicKey) WrapKey(rand io.Reader, uid []byte, hid byte, kLen int) ([]byte, []byte, error) {
|
||||
q := pub.GenerateUserPublicKey(uid, hid)
|
||||
var (
|
||||
err error
|
||||
r *bigmod.Nat
|
||||
w *bn256.GT
|
||||
cipher *bn256.G1
|
||||
key []byte
|
||||
)
|
||||
for {
|
||||
r, err = randomScalar(rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
rBytes := r.Bytes(orderNat)
|
||||
cipher, err = new(bn256.G1).ScalarMult(q, rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
w, err = pub.ScalarBaseMult(rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
var buffer []byte
|
||||
buffer = append(buffer, cipher.Marshal()...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
buffer = append(buffer, uid...)
|
||||
|
||||
key = sm3.Kdf(buffer, kLen)
|
||||
if subtle.ConstantTimeAllZero(key) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return key, cipher.MarshalUncompressed(), nil
|
||||
}
|
||||
|
||||
|
||||
// UnwrapKey decrypts the given cipher text using the private key and user ID (uid).
|
||||
// It returns the decrypted key of the specified length (kLen) or an error if decryption fails.
|
||||
func (priv *EncryptPrivateKey) UnwrapKey(uid, cipher []byte, kLen int) ([]byte, error) {
|
||||
if len(cipher) == 65 && cipher[0] != 0x04 {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
if len(cipher) == 65 {
|
||||
cipher = cipher[1:]
|
||||
}
|
||||
p := new(bn256.G1)
|
||||
_, err := p.Unmarshal(cipher)
|
||||
if err != nil || !p.IsOnCurve() {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
|
||||
w := bn256.Pair(p, priv.PrivateKey)
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(buffer, cipher...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
buffer = append(buffer, uid...)
|
||||
|
||||
key := sm3.Kdf(buffer, kLen)
|
||||
if subtle.ConstantTimeAllZero(key) == 1 {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// ErrDecryption represents a failure to decrypt a message.
|
||||
// It is deliberately vague to avoid adaptive attacks.
|
||||
var ErrDecryption = errors.New("sm9: decryption error")
|
||||
|
||||
// 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 {
|
||||
genSignature bool // control the optional sign/verify step triggered by responsder
|
||||
keyLength int // key length
|
||||
privateKey *EncryptPrivateKey // owner's encryption private key
|
||||
uid []byte // owner uid
|
||||
peerUID []byte // peer uid
|
||||
r *bigmod.Nat // random which will be used to compute secret
|
||||
secret []byte // generated secret which will be passed to peer
|
||||
peerSecret []byte // received peer's secret
|
||||
g1 *bn256.GT // internal state which will be used when compute the key and signature
|
||||
g2 *bn256.GT // internal state which will be used when compute the key and signature
|
||||
g3 *bn256.GT // internal state which will be used when compute the key and signature
|
||||
}
|
||||
|
||||
// NewKeyExchange creates one new KeyExchange object
|
||||
func (priv *EncryptPrivateKey) NewKeyExchange(uid, peerUID []byte, keyLen int, genSignature bool) *KeyExchange {
|
||||
ke := &KeyExchange{}
|
||||
ke.genSignature = genSignature
|
||||
ke.keyLength = keyLen
|
||||
ke.privateKey = priv
|
||||
ke.uid = uid
|
||||
ke.peerUID = peerUID
|
||||
return ke
|
||||
}
|
||||
|
||||
// Destroy clears all internal state and Ephemeral private/public keys
|
||||
func (ke *KeyExchange) Destroy() {
|
||||
if ke.r != nil {
|
||||
ke.r.SetBytes([]byte{0}, orderNat)
|
||||
}
|
||||
if ke.g1 != nil {
|
||||
ke.g1.SetOne()
|
||||
}
|
||||
if ke.g2 != nil {
|
||||
ke.g2.SetOne()
|
||||
}
|
||||
if ke.g3 != nil {
|
||||
ke.g3.SetOne()
|
||||
}
|
||||
}
|
||||
|
||||
func initKeyExchange(ke *KeyExchange, hid byte, r *bigmod.Nat) {
|
||||
pubB := ke.privateKey.GenerateUserPublicKey(ke.peerUID, hid)
|
||||
ke.r = r
|
||||
rA, err := new(bn256.G1).ScalarMult(pubB, ke.r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ke.secret = rA.MarshalUncompressed()
|
||||
}
|
||||
|
||||
// InitKeyExchange generates random with responder uid, for initiator's step A1-A4
|
||||
func (ke *KeyExchange) InitKeyExchange(rand io.Reader, hid byte) ([]byte, error) {
|
||||
r, err := randomScalar(rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
initKeyExchange(ke, hid, r)
|
||||
return ke.secret, nil
|
||||
}
|
||||
|
||||
func (ke *KeyExchange) sign(isResponder bool, prefix byte) []byte {
|
||||
var buffer []byte
|
||||
hash := sm3.New()
|
||||
hash.Write(ke.g2.Marshal())
|
||||
hash.Write(ke.g3.Marshal())
|
||||
if isResponder {
|
||||
hash.Write(ke.peerUID)
|
||||
hash.Write(ke.uid)
|
||||
hash.Write(ke.peerSecret[1:])
|
||||
hash.Write(ke.secret[1:])
|
||||
} else {
|
||||
hash.Write(ke.uid)
|
||||
hash.Write(ke.peerUID)
|
||||
hash.Write(ke.secret[1:])
|
||||
hash.Write(ke.peerSecret[1:])
|
||||
}
|
||||
buffer = hash.Sum(nil)
|
||||
hash.Reset()
|
||||
hash.Write([]byte{prefix})
|
||||
hash.Write(ke.g1.Marshal())
|
||||
hash.Write(buffer)
|
||||
return hash.Sum(nil)
|
||||
}
|
||||
|
||||
func (ke *KeyExchange) generateSharedKey(isResponder bool) ([]byte, error) {
|
||||
var buffer []byte
|
||||
if isResponder {
|
||||
buffer = append(buffer, ke.peerUID...)
|
||||
buffer = append(buffer, ke.uid...)
|
||||
buffer = append(buffer, ke.peerSecret[1:]...)
|
||||
buffer = append(buffer, ke.secret[1:]...)
|
||||
} else {
|
||||
buffer = append(buffer, ke.uid...)
|
||||
buffer = append(buffer, ke.peerUID...)
|
||||
buffer = append(buffer, ke.secret[1:]...)
|
||||
buffer = append(buffer, ke.peerSecret[1:]...)
|
||||
}
|
||||
buffer = append(buffer, ke.g1.Marshal()...)
|
||||
buffer = append(buffer, ke.g2.Marshal()...)
|
||||
buffer = append(buffer, ke.g3.Marshal()...)
|
||||
|
||||
return sm3.Kdf(buffer, ke.keyLength), nil
|
||||
}
|
||||
|
||||
func respondKeyExchange(ke *KeyExchange, hid byte, r *bigmod.Nat, rA []byte) ([]byte, []byte, error) {
|
||||
rP := new(bn256.G1)
|
||||
_, err := rP.Unmarshal(rA[1:])
|
||||
if err != nil || !rP.IsOnCurve() {
|
||||
return nil, nil, errors.New("sm9: invalid initiator's ephemeral public key")
|
||||
}
|
||||
ke.peerSecret = rA
|
||||
pubA := ke.privateKey.GenerateUserPublicKey(ke.peerUID, hid)
|
||||
ke.r = r
|
||||
rBytes := r.Bytes(orderNat)
|
||||
rB, err := new(bn256.G1).ScalarMult(pubA, rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.secret = rB.MarshalUncompressed()
|
||||
|
||||
ke.g1 = bn256.Pair(rP, ke.privateKey.PrivateKey)
|
||||
ke.g3 = &bn256.GT{}
|
||||
g3, err := bn256.ScalarMultGT(ke.g1, rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g3 = g3
|
||||
|
||||
g2, err := ke.privateKey.EncryptMasterPublicKey.ScalarBaseMult(rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g2 = g2
|
||||
|
||||
if !ke.genSignature {
|
||||
return ke.secret, nil, nil
|
||||
}
|
||||
|
||||
return ke.secret, ke.sign(true, 0x82), nil
|
||||
}
|
||||
|
||||
// RespondKeyExchange when responder receive rA, for responder's step B1-B7
|
||||
func (ke *KeyExchange) RespondKeyExchange(rand io.Reader, hid byte, rA []byte) ([]byte, []byte, error) {
|
||||
r, err := randomScalar(rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return respondKeyExchange(ke, hid, r, rA)
|
||||
}
|
||||
|
||||
// ConfirmResponder for initiator's step A5-A7
|
||||
func (ke *KeyExchange) ConfirmResponder(rB, sB []byte) ([]byte, []byte, error) {
|
||||
pB := new(bn256.G1)
|
||||
_, err := pB.Unmarshal(rB[1:])
|
||||
if err != nil || !pB.IsOnCurve() {
|
||||
return nil, nil, errors.New("sm9: invalid responder's ephemeral public key")
|
||||
}
|
||||
// step 5
|
||||
ke.peerSecret = rB
|
||||
g1, err := ke.privateKey.EncryptMasterPublicKey.ScalarBaseMult(ke.r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g1 = g1
|
||||
ke.g2 = bn256.Pair(pB, ke.privateKey.PrivateKey)
|
||||
ke.g3 = &bn256.GT{}
|
||||
g3, err := bn256.ScalarMultGT(ke.g2, ke.r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g3 = g3
|
||||
// step 6, verify signature
|
||||
if len(sB) > 0 {
|
||||
signature := ke.sign(false, 0x82)
|
||||
if goSubtle.ConstantTimeCompare(signature, sB) != 1 {
|
||||
return nil, nil, errors.New("sm9: invalid responder's signature")
|
||||
}
|
||||
}
|
||||
key, err := ke.generateSharedKey(false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !ke.genSignature {
|
||||
return key, nil, nil
|
||||
}
|
||||
return key, ke.sign(false, 0x83), nil
|
||||
}
|
||||
|
||||
// ConfirmInitiator for responder's step B8
|
||||
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) ([]byte, error) {
|
||||
if s1 != nil {
|
||||
buffer := ke.sign(true, 0x83)
|
||||
if goSubtle.ConstantTimeCompare(buffer, s1) != 1 {
|
||||
return nil, errors.New("sm9: invalid initiator's signature")
|
||||
}
|
||||
}
|
||||
return ke.generateSharedKey(true)
|
||||
}
|
510
internal/sm9/sm9_key.go
Normal file
510
internal/sm9/sm9_key.go
Normal file
@ -0,0 +1,510 @@
|
||||
package sm9
|
||||
|
||||
import (
|
||||
_subtle "crypto/subtle"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"io"
|
||||
"math/bits"
|
||||
"sync"
|
||||
|
||||
"slices"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/bigmod"
|
||||
"github.com/emmansun/gmsm/internal/randutil"
|
||||
"github.com/emmansun/gmsm/internal/sm9/bn256"
|
||||
"github.com/emmansun/gmsm/internal/subtle"
|
||||
)
|
||||
|
||||
// SignMasterPrivateKey master private key for sign, generated by KGC
|
||||
type SignMasterPrivateKey struct {
|
||||
*SignMasterPublicKey // master public key
|
||||
privateKey []byte // master private key
|
||||
}
|
||||
|
||||
// SignMasterPublicKey master public key for sign, generated by KGC
|
||||
type SignMasterPublicKey struct {
|
||||
MasterPublicKey *bn256.G2 // master public key
|
||||
pairOnce sync.Once
|
||||
basePoint *bn256.GT // the result of Pair(Gen1, pub.MasterPublicKey)
|
||||
tableGenOnce sync.Once
|
||||
table *[32 * 2]bn256.GTFieldTable // precomputed basePoint^n
|
||||
}
|
||||
|
||||
// SignPrivateKey user private key for sign, generated by KGC
|
||||
type SignPrivateKey struct {
|
||||
PrivateKey *bn256.G1 // user private key
|
||||
*SignMasterPublicKey // master public key
|
||||
}
|
||||
|
||||
// EncryptMasterPrivateKey master private key for encryption, generated by KGC
|
||||
type EncryptMasterPrivateKey struct {
|
||||
*EncryptMasterPublicKey // master public key
|
||||
privateKey []byte // master private key
|
||||
}
|
||||
|
||||
// EncryptMasterPublicKey master private key for encryption, generated by KGC
|
||||
type EncryptMasterPublicKey struct {
|
||||
MasterPublicKey *bn256.G1 // public key
|
||||
pairOnce sync.Once
|
||||
basePoint *bn256.GT // the result of Pair(pub.MasterPublicKey, Gen2)
|
||||
tableGenOnce sync.Once
|
||||
table *[32 * 2]bn256.GTFieldTable // precomputed basePoint^n
|
||||
}
|
||||
|
||||
// EncryptPrivateKey user private key for encryption, generated by KGC
|
||||
type EncryptPrivateKey struct {
|
||||
PrivateKey *bn256.G2 // user private key
|
||||
*EncryptMasterPublicKey // master public key
|
||||
}
|
||||
|
||||
// GenerateSignMasterKey generates a master public and private key pair for DSA usage.
|
||||
func GenerateSignMasterKey(rand io.Reader) (*SignMasterPrivateKey, error) {
|
||||
key := make([]byte, len(bn256.OrderMinus1Bytes))
|
||||
randutil.MaybeReadByte(rand)
|
||||
|
||||
for {
|
||||
if _, err := io.ReadFull(rand, key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// In tests, rand will return all zeros and NewPrivateKey will reject
|
||||
// the zero key as it generates the identity as a public key. This also
|
||||
// makes this function consistent with crypto/elliptic.GenerateKey.
|
||||
key[1] ^= 0x42
|
||||
|
||||
k, err := NewSignMasterPrivateKey(key)
|
||||
if err == errInvalidPrivateKey {
|
||||
continue
|
||||
}
|
||||
return k, err
|
||||
}
|
||||
}
|
||||
|
||||
// NewSignMasterPrivateKey creates a new SignMasterPrivateKey from the given byte slice.
|
||||
// The provided key must have the same length as bn256.OrderMinus1Bytes and must be less than bn256.OrderMinus1Bytes.
|
||||
// If the key is invalid, an error is returned.
|
||||
//
|
||||
// Parameters:
|
||||
// - key: A byte slice representing the master private key.
|
||||
//
|
||||
// Returns:
|
||||
// - *SignMasterPrivateKey: A pointer to the newly created SignMasterPrivateKey.
|
||||
// - error: An error if the key is invalid or if there is an issue during key generation.
|
||||
func NewSignMasterPrivateKey(key []byte) (*SignMasterPrivateKey, error) {
|
||||
if len(key) != len(bn256.OrderMinus1Bytes) {
|
||||
return nil, errors.New("sm9: invalid master sign private key size")
|
||||
}
|
||||
if subtle.ConstantTimeAllZero(key) == 1 || !isLess(key, bn256.OrderMinus1Bytes) {
|
||||
return nil, errInvalidPrivateKey
|
||||
}
|
||||
p, err := new(bn256.G2).ScalarBaseMult(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv := new(SignMasterPrivateKey)
|
||||
priv.privateKey = append([]byte{}, key...)
|
||||
priv.SignMasterPublicKey = new(SignMasterPublicKey)
|
||||
priv.MasterPublicKey = p
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
// Equal compares the receiver SignMasterPrivateKey with another SignMasterPrivateKey x.
|
||||
// It returns true if both the MasterPublicKey and privateKey fields are equal, using
|
||||
// constant time comparison for the privateKey to prevent timing attacks.
|
||||
func (master *SignMasterPrivateKey) Equal(x *SignMasterPrivateKey) bool {
|
||||
return master.MasterPublicKey.Equal(x.MasterPublicKey) && _subtle.ConstantTimeCompare(master.privateKey, x.privateKey) == 1
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the SignMasterPrivateKey.
|
||||
// It creates a new byte slice and appends the private key bytes to it,
|
||||
// ensuring that the original private key data is not modified.
|
||||
func (master *SignMasterPrivateKey) Bytes() []byte {
|
||||
return slices.Clone(master.privateKey)
|
||||
}
|
||||
|
||||
// GenerateUserKey generate an user dsa key.
|
||||
func (master *SignMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*SignPrivateKey, error) {
|
||||
var id []byte
|
||||
id = append(append(id, uid...), hid)
|
||||
|
||||
t1Nat := hashH1(id)
|
||||
|
||||
d, err := bigmod.NewNat().SetBytes(master.privateKey, orderNat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t1Nat.Add(d, orderNat)
|
||||
if t1Nat.IsZero() == 1 {
|
||||
return nil, errors.New("sm9: need to re-generate sign master private key")
|
||||
}
|
||||
|
||||
t1Nat = bigmod.NewNat().Exp(t1Nat, bn256.OrderMinus2Bytes, orderNat)
|
||||
t1Nat.Mul(d, orderNat)
|
||||
|
||||
priv := new(SignPrivateKey)
|
||||
priv.SignMasterPublicKey = master.SignMasterPublicKey
|
||||
g1, err := new(bn256.G1).ScalarBaseMult(t1Nat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv.PrivateKey = g1
|
||||
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
// Public returns the public key corresponding to priv.
|
||||
func (master *SignMasterPrivateKey) Public() *SignMasterPublicKey {
|
||||
return master.SignMasterPublicKey
|
||||
}
|
||||
|
||||
// Equal compares the receiver SignMasterPublicKey with another SignMasterPublicKey
|
||||
// and returns true if they are equal, otherwise it returns false.
|
||||
func (pub *SignMasterPublicKey) Equal(x *SignMasterPublicKey) bool {
|
||||
return pub.MasterPublicKey.Equal(x.MasterPublicKey)
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the SignMasterPublicKey
|
||||
// by marshaling the MasterPublicKey in an uncompressed format.
|
||||
func (pub *SignMasterPublicKey) Bytes() []byte {
|
||||
return pub.MasterPublicKey.MarshalUncompressed()
|
||||
}
|
||||
|
||||
// pair generate the basepoint once
|
||||
func (pub *SignMasterPublicKey) pair() *bn256.GT {
|
||||
pub.pairOnce.Do(func() {
|
||||
pub.basePoint = bn256.Pair(bn256.Gen1, pub.MasterPublicKey)
|
||||
})
|
||||
return pub.basePoint
|
||||
}
|
||||
|
||||
func (pub *SignMasterPublicKey) generatorTable() *[32 * 2]bn256.GTFieldTable {
|
||||
pub.tableGenOnce.Do(func() {
|
||||
pub.table = bn256.GenerateGTFieldTable(pub.pair())
|
||||
})
|
||||
return pub.table
|
||||
}
|
||||
|
||||
// ScalarBaseMult compute basepoint^r with precomputed table
|
||||
// The base point = pair(Gen1, <master public key>)
|
||||
func (pub *SignMasterPublicKey) ScalarBaseMult(scalar []byte) (*bn256.GT, error) {
|
||||
tables := pub.generatorTable()
|
||||
return bn256.ScalarBaseMultGT(tables, scalar)
|
||||
}
|
||||
|
||||
// GenerateUserPublicKey generate user sign public key
|
||||
func (pub *SignMasterPublicKey) GenerateUserPublicKey(uid []byte, hid byte) *bn256.G2 {
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, uid...), hid)
|
||||
h1 := hashH1(buffer)
|
||||
p, err := new(bn256.G2).ScalarBaseMult(h1.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.Add(p, pub.MasterPublicKey)
|
||||
return p
|
||||
}
|
||||
|
||||
// Equal compares the SignPrivateKey receiver with another SignPrivateKey x
|
||||
// and returns true if they are equal, otherwise it returns false.
|
||||
func (priv *SignPrivateKey) Equal(x *SignPrivateKey) bool {
|
||||
return priv.PrivateKey.Equal(x.PrivateKey)
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the SignPrivateKey.
|
||||
// It marshals the private key in an uncompressed format.
|
||||
func (priv *SignPrivateKey) Bytes() []byte {
|
||||
return priv.PrivateKey.MarshalUncompressed()
|
||||
}
|
||||
|
||||
// MasterPublic returns the master public key corresponding to priv.
|
||||
func (priv *SignPrivateKey) MasterPublic() *SignMasterPublicKey {
|
||||
return priv.SignMasterPublicKey
|
||||
}
|
||||
|
||||
// SetMasterPublicKey bind the sign master public key to it.
|
||||
func (priv *SignPrivateKey) SetMasterPublicKey(pub *SignMasterPublicKey) {
|
||||
if priv.SignMasterPublicKey == nil || priv.SignMasterPublicKey.MasterPublicKey == nil {
|
||||
priv.SignMasterPublicKey = pub
|
||||
}
|
||||
}
|
||||
|
||||
func unmarshalG2(bytes []byte) (*bn256.G2, error) {
|
||||
g2 := new(bn256.G2)
|
||||
switch bytes[0] {
|
||||
case 4:
|
||||
_, err := g2.Unmarshal(bytes[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 2, 3:
|
||||
_, err := g2.UnmarshalCompressed(bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("sm9: invalid point identity byte")
|
||||
}
|
||||
return g2, nil
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to sign master public key
|
||||
func (pub *SignMasterPublicKey) UnmarshalRaw(bytes []byte) error {
|
||||
g2, err := unmarshalG2(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pub.MasterPublicKey = g2
|
||||
return nil
|
||||
}
|
||||
|
||||
func unmarshalG1(bytes []byte) (*bn256.G1, error) {
|
||||
g := new(bn256.G1)
|
||||
switch bytes[0] {
|
||||
case 4:
|
||||
_, err := g.Unmarshal(bytes[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 2, 3:
|
||||
_, err := g.UnmarshalCompressed(bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("sm9: invalid point identity byte")
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to sign user private key
|
||||
// Note, priv's SignMasterPublicKey should be handled separately.
|
||||
func (priv *SignPrivateKey) UnmarshalRaw(bytes []byte) error {
|
||||
g, err := unmarshalG1(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
priv.PrivateKey = g
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateEncryptMasterKey generates a master public and private key pair for encryption usage.
|
||||
func GenerateEncryptMasterKey(rand io.Reader) (*EncryptMasterPrivateKey, error) {
|
||||
key := make([]byte, len(bn256.OrderMinus1Bytes))
|
||||
randutil.MaybeReadByte(rand)
|
||||
|
||||
for {
|
||||
if _, err := io.ReadFull(rand, key); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// In tests, rand will return all zeros and NewPrivateKey will reject
|
||||
// the zero key as it generates the identity as a public key. This also
|
||||
// makes this function consistent with crypto/elliptic.GenerateKey.
|
||||
key[1] ^= 0x42
|
||||
|
||||
k, err := NewEncryptMasterPrivateKey(key)
|
||||
if err == errInvalidPrivateKey {
|
||||
continue
|
||||
}
|
||||
return k, err
|
||||
}
|
||||
}
|
||||
|
||||
// NewEncryptMasterPrivateKey creates a new EncryptMasterPrivateKey from the given key bytes.
|
||||
// The key must have a length equal to bn256.OrderMinus1Bytes. If the key is all zeros or not
|
||||
// less than bn256.OrderMinus1Bytes, an error is returned.
|
||||
//
|
||||
// Parameters:
|
||||
// - key: A byte slice representing the master private key.
|
||||
//
|
||||
// Returns:
|
||||
// - *EncryptMasterPrivateKey: A pointer to the newly created EncryptMasterPrivateKey.
|
||||
// - error: An error if the key is invalid or if there is an issue during key generation.
|
||||
func NewEncryptMasterPrivateKey(key []byte) (*EncryptMasterPrivateKey, error) {
|
||||
if len(key) != len(bn256.OrderMinus1Bytes) {
|
||||
return nil, errors.New("sm9: invalid master encrypt private key size")
|
||||
}
|
||||
if subtle.ConstantTimeAllZero(key) == 1 || !isLess(key, bn256.OrderMinus1Bytes) {
|
||||
return nil, errInvalidPrivateKey
|
||||
}
|
||||
p, err := new(bn256.G1).ScalarBaseMult(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv := new(EncryptMasterPrivateKey)
|
||||
priv.privateKey = append([]byte{}, key...)
|
||||
priv.EncryptMasterPublicKey = new(EncryptMasterPublicKey)
|
||||
priv.MasterPublicKey = p
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
// Bytes returns a copy of the private key bytes from the EncryptMasterPrivateKey.
|
||||
// This method ensures that the original private key data is not modified by
|
||||
// returning a new slice containing the same data.
|
||||
func (master *EncryptMasterPrivateKey) Bytes() []byte {
|
||||
return append([]byte{}, master.privateKey...)
|
||||
}
|
||||
|
||||
// Equal compares the receiver EncryptMasterPrivateKey with another EncryptMasterPrivateKey x.
|
||||
// It returns true if both the public keys and private keys are equal, otherwise it returns false.
|
||||
// The comparison of private keys is done in constant time to prevent timing attacks.
|
||||
func (master *EncryptMasterPrivateKey) Equal(x *EncryptMasterPrivateKey) bool {
|
||||
return master.EncryptMasterPublicKey.Equal(x.EncryptMasterPublicKey) && _subtle.ConstantTimeCompare(master.privateKey, x.privateKey) == 1
|
||||
}
|
||||
|
||||
// GenerateUserKey generate an user key for encryption.
|
||||
func (master *EncryptMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*EncryptPrivateKey, error) {
|
||||
var id []byte
|
||||
id = append(append(id, uid...), hid)
|
||||
|
||||
t1Nat := hashH1(id)
|
||||
|
||||
d, err := bigmod.NewNat().SetBytes(master.privateKey, orderNat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t1Nat.Add(d, orderNat)
|
||||
if t1Nat.IsZero() == 1 {
|
||||
return nil, errors.New("sm9: need to re-generate encrypt master private key")
|
||||
}
|
||||
|
||||
t1Nat = bigmod.NewNat().Exp(t1Nat, bn256.OrderMinus2Bytes, orderNat)
|
||||
t1Nat.Mul(d, orderNat)
|
||||
|
||||
priv := new(EncryptPrivateKey)
|
||||
priv.EncryptMasterPublicKey = master.EncryptMasterPublicKey
|
||||
p, err := new(bn256.G2).ScalarBaseMult(t1Nat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
priv.PrivateKey = p
|
||||
|
||||
return priv, nil
|
||||
}
|
||||
|
||||
// Public returns the public key corresponding to priv.
|
||||
func (master *EncryptMasterPrivateKey) Public() *EncryptMasterPublicKey {
|
||||
return master.EncryptMasterPublicKey
|
||||
}
|
||||
|
||||
// Equal compares the receiver EncryptMasterPublicKey with another EncryptMasterPublicKey
|
||||
// and returns true if they are equal, otherwise false.
|
||||
func (pub *EncryptMasterPublicKey) Equal(x *EncryptMasterPublicKey) bool {
|
||||
return pub.MasterPublicKey.Equal(x.MasterPublicKey)
|
||||
}
|
||||
|
||||
func (pub *EncryptMasterPublicKey) Bytes() []byte {
|
||||
return pub.MasterPublicKey.MarshalUncompressed()
|
||||
}
|
||||
|
||||
// pair generate the basepoint once
|
||||
func (pub *EncryptMasterPublicKey) pair() *bn256.GT {
|
||||
pub.pairOnce.Do(func() {
|
||||
pub.basePoint = bn256.Pair(pub.MasterPublicKey, bn256.Gen2)
|
||||
})
|
||||
return pub.basePoint
|
||||
}
|
||||
|
||||
func (pub *EncryptMasterPublicKey) generatorTable() *[32 * 2]bn256.GTFieldTable {
|
||||
pub.tableGenOnce.Do(func() {
|
||||
pub.table = bn256.GenerateGTFieldTable(pub.pair())
|
||||
})
|
||||
return pub.table
|
||||
}
|
||||
|
||||
// ScalarBaseMult compute basepoint^r with precomputed table.
|
||||
// The base point = pair(<master public key>, Gen2)
|
||||
func (pub *EncryptMasterPublicKey) ScalarBaseMult(scalar []byte) (*bn256.GT, error) {
|
||||
tables := pub.generatorTable()
|
||||
return bn256.ScalarBaseMultGT(tables, scalar)
|
||||
}
|
||||
|
||||
// GenerateUserPublicKey generate user encrypt public key
|
||||
func (pub *EncryptMasterPublicKey) GenerateUserPublicKey(uid []byte, hid byte) *bn256.G1 {
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, uid...), hid)
|
||||
h1 := hashH1(buffer)
|
||||
p, err := new(bn256.G1).ScalarBaseMult(h1.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.Add(p, pub.MasterPublicKey)
|
||||
return p
|
||||
}
|
||||
|
||||
// Equal compares the calling EncryptPrivateKey with another EncryptPrivateKey
|
||||
// and returns true if they are equal, otherwise it returns false.
|
||||
func (priv *EncryptPrivateKey) Equal(x *EncryptPrivateKey) bool {
|
||||
return priv.PrivateKey.Equal(x.PrivateKey)
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the EncryptPrivateKey.
|
||||
// It marshals the private key in an uncompressed format.
|
||||
func (priv *EncryptPrivateKey) Bytes() []byte {
|
||||
return priv.PrivateKey.MarshalUncompressed()
|
||||
}
|
||||
|
||||
// MasterPublic returns the master public key corresponding to priv.
|
||||
func (priv *EncryptPrivateKey) MasterPublic() *EncryptMasterPublicKey {
|
||||
return priv.EncryptMasterPublicKey
|
||||
}
|
||||
|
||||
// SetMasterPublicKey bind the encrypt master public key to it.
|
||||
func (priv *EncryptPrivateKey) SetMasterPublicKey(pub *EncryptMasterPublicKey) {
|
||||
if priv.EncryptMasterPublicKey == nil || priv.EncryptMasterPublicKey.MasterPublicKey == nil {
|
||||
priv.EncryptMasterPublicKey = pub
|
||||
}
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to encrypt master public key
|
||||
func (pub *EncryptMasterPublicKey) UnmarshalRaw(bytes []byte) error {
|
||||
g, err := unmarshalG1(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pub.MasterPublicKey = g
|
||||
return nil
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to encrypt user private key
|
||||
// Note, priv's EncryptMasterPublicKey should be handled separately.
|
||||
func (priv *EncryptPrivateKey) UnmarshalRaw(bytes []byte) error {
|
||||
g, err := unmarshalG2(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
priv.PrivateKey = g
|
||||
return nil
|
||||
}
|
||||
|
||||
// isLess returns whether a < b, where a and b are big-endian buffers of the
|
||||
// same length and shorter than 72 bytes.
|
||||
func isLess(a, b []byte) bool {
|
||||
if len(a) != len(b) {
|
||||
panic("sm9: internal error: mismatched isLess inputs")
|
||||
}
|
||||
|
||||
// Copy the values into a fixed-size preallocated little-endian buffer.
|
||||
// 72 bytes is enough for every scalar in this package, and having a fixed
|
||||
// size lets us avoid heap allocations.
|
||||
if len(a) > 72 {
|
||||
panic("sm9: internal error: isLess input too large")
|
||||
}
|
||||
bufA, bufB := make([]byte, 72), make([]byte, 72)
|
||||
for i := range a {
|
||||
bufA[i], bufB[i] = a[len(a)-i-1], b[len(b)-i-1]
|
||||
}
|
||||
|
||||
// Perform a subtraction with borrow.
|
||||
var borrow uint64
|
||||
for i := 0; i < len(bufA); i += 8 {
|
||||
limbA, limbB := binary.LittleEndian.Uint64(bufA[i:]), binary.LittleEndian.Uint64(bufB[i:])
|
||||
_, borrow = bits.Sub64(limbA, limbB, borrow)
|
||||
}
|
||||
|
||||
// If there is a borrow at the end of the operation, then a < b.
|
||||
return borrow == 1
|
||||
}
|
||||
|
||||
var errInvalidPrivateKey = errors.New("sm9: invalid private key")
|
40
internal/sm9/sm9_key_test.go
Normal file
40
internal/sm9/sm9_key_test.go
Normal file
@ -0,0 +1,40 @@
|
||||
package sm9
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
}
|
596
internal/sm9/sm9_test.go
Normal file
596
internal/sm9/sm9_test.go
Normal file
@ -0,0 +1,596 @@
|
||||
package sm9
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"crypto/subtle"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/alias"
|
||||
"github.com/emmansun/gmsm/internal/bigmod"
|
||||
"github.com/emmansun/gmsm/internal/sm3"
|
||||
"github.com/emmansun/gmsm/internal/sm4"
|
||||
"github.com/emmansun/gmsm/internal/sm9/bn256"
|
||||
)
|
||||
|
||||
func TestHashH1(t *testing.T) {
|
||||
expected := "2acc468c3926b0bdb2767e99ff26e084de9ced8dbc7d5fbf418027b667862fab"
|
||||
h := hashH1([]byte{0x41, 0x6c, 0x69, 0x63, 0x65, 0x01})
|
||||
if hex.EncodeToString(h.Bytes(orderNat)) != expected {
|
||||
t.Errorf("got %v, expected %v", h.Bytes(orderNat), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashH2(t *testing.T) {
|
||||
expected := "823c4b21e4bd2dfe1ed92c606653e996668563152fc33f55d7bfbb9bd9705adb"
|
||||
zStr := "4368696E65736520494253207374616E6461726481377B8FDBC2839B4FA2D0E0F8AA6853BBBE9E9C4099608F8612C6078ACD7563815AEBA217AD502DA0F48704CC73CABB3C06209BD87142E14CBD99E8BCA1680F30DADC5CD9E207AEE32209F6C3CA3EC0D800A1A42D33C73153DED47C70A39D2E8EAF5D179A1836B359A9D1D9BFC19F2EFCDB829328620962BD3FDF15F2567F58A543D25609AE943920679194ED30328BB33FD15660BDE485C6B79A7B32B013983F012DB04BA59FE88DB889321CC2373D4C0C35E84F7AB1FF33679BCA575D67654F8624EB435B838CCA77B2D0347E65D5E46964412A096F4150D8C5EDE5440DDF0656FCB663D24731E80292188A2471B8B68AA993899268499D23C89755A1A89744643CEAD40F0965F28E1CD2895C3D118E4F65C9A0E3E741B6DD52C0EE2D25F5898D60848026B7EFB8FCC1B2442ECF0795F8A81CEE99A6248F294C82C90D26BD6A814AAF475F128AEF43A128E37F80154AE6CB92CAD7D1501BAE30F750B3A9BD1F96B08E97997363911314705BFB9A9DBB97F75553EC90FBB2DDAE53C8F68E42"
|
||||
z, err := hex.DecodeString(zStr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := hashH2(z)
|
||||
if hex.EncodeToString(h.Bytes(orderNat)) != expected {
|
||||
t.Errorf("got %v, expected %v", h.Bytes(orderNat), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
hid := byte(0x01)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h, s, err := userKey.Sign(rand.Reader, hashed, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !masterKey.Public().Verify(uid, hid, hashed, h, s) {
|
||||
t.Errorf("Verify failed")
|
||||
}
|
||||
sNeg := new(bn256.G1)
|
||||
sNeg.Unmarshal(s[1:])
|
||||
sNeg.Neg(sNeg)
|
||||
if masterKey.Public().Verify(uid, hid, hashed, h, sNeg.MarshalUncompressed()) {
|
||||
t.Errorf("Verify with s=-s succeeded")
|
||||
}
|
||||
hashed[0] ^= 0xff
|
||||
if masterKey.Public().Verify(uid, hid, hashed, h, s) {
|
||||
t.Errorf("Verify always works!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeInputs(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
hid := byte(0x01)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := new(big.Int).SetInt64(1)
|
||||
h.Lsh(h, 550 /* larger than any supported curve */)
|
||||
h.Neg(h)
|
||||
if masterKey.Public().Verify(uid, hid, hashed, h.Bytes(), bn256.Gen1.MarshalUncompressed()) {
|
||||
t.Errorf("bogus signature accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestZeroSignature(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
hid := byte(0x01)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if masterKey.Public().Verify(uid, hid, hashed, big.NewInt(0).Bytes(), bn256.Gen1.MarshalUncompressed()) {
|
||||
t.Error("Verify with h=0 succeeded")
|
||||
}
|
||||
if masterKey.Public().Verify(uid, hid, hashed, bn256.OrderBytes, bn256.Gen1.MarshalUncompressed()) {
|
||||
t.Error("Verify with h=order succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix A
|
||||
func TestSignSM9Sample(t *testing.T) {
|
||||
expectedH, _ := hex.DecodeString("823c4b21e4bd2dfe1ed92c606653e996668563152fc33f55d7bfbb9bd9705adb")
|
||||
expectedHNat, err := bigmod.NewNat().SetBytes(expectedH, orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedS := "0473bf96923ce58b6ad0e13e9643a406d8eb98417c50ef1b29cef9adb48b6d598c856712f1c2e0968ab7769f42a99586aed139d5b8b3e15891827cc2aced9baa05"
|
||||
hash := []byte("Chinese IBS standard")
|
||||
hid := byte(0x01)
|
||||
uid := []byte("Alice")
|
||||
r, _ := hex.DecodeString("033c8616b06704813203dfd00965022ed15975c662337aed648835dc4b1cbe")
|
||||
rNat, err := bigmod.NewNat().SetBytes(r, orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
kb, _ := hex.DecodeString("000130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4")
|
||||
masterKey, err := NewSignMasterPrivateKey(kb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w, err := userKey.SignMasterPublicKey.ScalarBaseMult(bn256.NormalizeScalar(r))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(buffer, hash...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
|
||||
h := hashH2(buffer)
|
||||
if h.Equal(expectedHNat) == 0 {
|
||||
t.Fatal("not same h")
|
||||
}
|
||||
|
||||
rNat.Sub(h, orderNat)
|
||||
|
||||
s, err := new(bn256.G1).ScalarMult(userKey.PrivateKey, rNat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(s.MarshalUncompressed()) != expectedS {
|
||||
t.Fatal("not same S")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapKey(t *testing.T) {
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
hid := byte(0x01)
|
||||
uid := []byte("emmansun")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
key, cipher, err := masterKey.Public().WrapKey(rand.Reader, uid, hid, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key2, err := userKey.UnwrapKey(uid, cipher, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if !bytes.Equal(key, key2) {
|
||||
t.Errorf("expected %x, got %x", key, key2)
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix C
|
||||
func TestWrapKeySM9Sample(t *testing.T) {
|
||||
expectedMasterPublicKey := "787ed7b8a51f3ab84e0a66003f32da5c720b17eca7137d39abc66e3c80a892ff769de61791e5adc4b9ff85a31354900b202871279a8c49dc3f220f644c57a7b1"
|
||||
expectedUserPrivateKey := "94736acd2c8c8796cc4785e938301a139a059d3537b6414140b2d31eecf41683115bae85f5d8bc6c3dbd9e5342979acccf3c2f4f28420b1cb4f8c0b59a19b1587aa5e47570da7600cd760a0cf7beaf71c447f3844753fe74fa7ba92ca7d3b55f27538a62e7f7bfb51dce08704796d94c9d56734f119ea44732b50e31cdeb75c1"
|
||||
expectedUserPublicKey := "709d165808b0a43e2574e203fa885abcbab16a240c4c1916552e7c43d09763b8693269a6be2456f43333758274786b6051ff87b7f198da4ba1a2c6e336f51fcc"
|
||||
expectedCipher := "1edee2c3f465914491de44cefb2cb434ab02c308d9dc5e2067b4fed5aaac8a0f1c9b4c435eca35ab83bb734174c0f78fde81a53374aff3b3602bbc5e37be9a4c"
|
||||
expectedKey := "4ff5cf86d2ad40c8f4bac98d76abdbde0c0e2f0a829d3f911ef5b2bce0695480"
|
||||
|
||||
kb, _ := hex.DecodeString("0001EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22")
|
||||
masterKey, err := NewEncryptMasterPrivateKey(kb)
|
||||
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")
|
||||
}
|
||||
|
||||
rb, _ := hex.DecodeString("74015F8489C01EF4270456F9E6475BFB602BDE7F33FD482AB4E3684A6722")
|
||||
var r *big.Int = new(big.Int).SetBytes(rb)
|
||||
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 := sm3.Kdf(buffer, 32)
|
||||
|
||||
if hex.EncodeToString(key) != expectedKey {
|
||||
t.Errorf("expected %v, got %v\n", expectedKey, hex.EncodeToString(key))
|
||||
}
|
||||
|
||||
key2, err := userKey.UnwrapKey(uid, cipher.MarshalUncompressed(), 32)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hex.EncodeToString(key2) != expectedKey {
|
||||
t.Errorf("expected %v, got %v\n", expectedKey, hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix D
|
||||
func TestEncryptSM9Sample(t *testing.T) {
|
||||
plaintext := []byte("Chinese IBE standard")
|
||||
expectedMasterPublicKey := "787ed7b8a51f3ab84e0a66003f32da5c720b17eca7137d39abc66e3c80a892ff769de61791e5adc4b9ff85a31354900b202871279a8c49dc3f220f644c57a7b1"
|
||||
expectedUserPrivateKey := "94736acd2c8c8796cc4785e938301a139a059d3537b6414140b2d31eecf41683115bae85f5d8bc6c3dbd9e5342979acccf3c2f4f28420b1cb4f8c0b59a19b1587aa5e47570da7600cd760a0cf7beaf71c447f3844753fe74fa7ba92ca7d3b55f27538a62e7f7bfb51dce08704796d94c9d56734f119ea44732b50e31cdeb75c1"
|
||||
expectedUserPublicKey := "709d165808b0a43e2574e203fa885abcbab16a240c4c1916552e7c43d09763b8693269a6be2456f43333758274786b6051ff87b7f198da4ba1a2c6e336f51fcc"
|
||||
expectedCipher := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0"
|
||||
expectedKey := "58373260f067ec48667c21c144f8bc33cd3049788651ffd5f738003e51df31174d0e4e402fd87f4581b612f74259db574f67ece6"
|
||||
expectedCiphertext := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0ba672387bcd6de5016a158a52bb2e7fc429197bcab70b25afee37a2b9db9f3671b5f5b0e951489682f3e64e1378cdd5da9513b1c"
|
||||
|
||||
kb, _ := hex.DecodeString("0001EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22")
|
||||
masterKey, err := NewEncryptMasterPrivateKey(kb)
|
||||
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")
|
||||
}
|
||||
|
||||
rb, _ := hex.DecodeString("AAC0541779C8FC45E3E2CB25C12B5D2576B2129AE8BB5EE2CBE5EC9E785C")
|
||||
var r *big.Int = new(big.Int).SetBytes(rb)
|
||||
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 := sm3.Kdf(buffer, len(plaintext)+32)
|
||||
|
||||
if hex.EncodeToString(key) != expectedKey {
|
||||
t.Errorf("not expected key")
|
||||
}
|
||||
subtle.XORBytes(key, key[:len(plaintext)], plaintext)
|
||||
|
||||
hash := sm3.New()
|
||||
hash.Write(key)
|
||||
c3 := hash.Sum(nil)
|
||||
|
||||
ciphertext := append(cipher.Marshal(), c3...)
|
||||
ciphertext = append(ciphertext, key[:len(plaintext)]...)
|
||||
if hex.EncodeToString(ciphertext) != expectedCiphertext {
|
||||
t.Errorf("expected %v, got %v\n", expectedCiphertext, hex.EncodeToString(ciphertext))
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncryptSM9SampleBlockMode(t *testing.T) {
|
||||
plaintext := []byte("Chinese IBE standard")
|
||||
expectedMasterPublicKey := "787ed7b8a51f3ab84e0a66003f32da5c720b17eca7137d39abc66e3c80a892ff769de61791e5adc4b9ff85a31354900b202871279a8c49dc3f220f644c57a7b1"
|
||||
expectedUserPrivateKey := "94736acd2c8c8796cc4785e938301a139a059d3537b6414140b2d31eecf41683115bae85f5d8bc6c3dbd9e5342979acccf3c2f4f28420b1cb4f8c0b59a19b1587aa5e47570da7600cd760a0cf7beaf71c447f3844753fe74fa7ba92ca7d3b55f27538a62e7f7bfb51dce08704796d94c9d56734f119ea44732b50e31cdeb75c1"
|
||||
expectedUserPublicKey := "709d165808b0a43e2574e203fa885abcbab16a240c4c1916552e7c43d09763b8693269a6be2456f43333758274786b6051ff87b7f198da4ba1a2c6e336f51fcc"
|
||||
expectedCipher := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0"
|
||||
expectedKey := "58373260f067ec48667c21c144f8bc33cd3049788651ffd5f738003e51df31174d0e4e402fd87f4581b612f74259db57"
|
||||
expectedCiphertext := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0fd3c98dd92c44c68332675a370cceede31e0c5cd209c257601149d12b394a2bee05b6fac6f11b965268c994f00dba7a8bb00fd60583546cbdf4649250863f10a"
|
||||
|
||||
kb, _ := hex.DecodeString("0001EDEE3778F441F8DEA3D9FA0ACC4E07EE36C93F9A08618AF4AD85CEDE1C22")
|
||||
masterKey, err := NewEncryptMasterPrivateKey(kb)
|
||||
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")
|
||||
}
|
||||
|
||||
rb, _ := hex.DecodeString("AAC0541779C8FC45E3E2CB25C12B5D2576B2129AE8BB5EE2CBE5EC9E785C")
|
||||
var r *big.Int = new(big.Int).SetBytes(rb)
|
||||
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 := sm3.Kdf(buffer, 16+32)
|
||||
|
||||
if hex.EncodeToString(key) != expectedKey {
|
||||
t.Errorf("not expected key, expected %v, got %x\n", expectedKey, key)
|
||||
}
|
||||
|
||||
// ECB mode with PKCS7 padding
|
||||
block, err := sm4.NewCipher(key[:16])
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
overhead := sm4.BlockSize - len(plaintext)%sm4.BlockSize
|
||||
c2, out := alias.SliceForAppend(plaintext, overhead)
|
||||
for i := range overhead {
|
||||
out[i] = byte(overhead)
|
||||
}
|
||||
ret := c2
|
||||
for len(ret) > 0 {
|
||||
block.Encrypt(ret, ret)
|
||||
ret = ret[sm4.BlockSize:]
|
||||
}
|
||||
|
||||
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 TestKeyExchange(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := userKey.NewKeyExchange(userA, userB, 16, true)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := userKey.NewKeyExchange(userB, userA, 16, true)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
rA, err := initiator.InitKeyExchange(rand.Reader, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
rB, sigB, err := responder.RespondKeyExchange(rand.Reader, hid, rA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B8
|
||||
key2, err := responder.ConfirmInitiator(sigA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("got different key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyExchangeWithoutSignature(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := userKey.NewKeyExchange(userA, userB, 16, false)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := userKey.NewKeyExchange(userB, userA, 16, false)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
rA, err := initiator.InitKeyExchange(rand.Reader, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
rB, sigB, err := responder.RespondKeyExchange(rand.Reader, hid, rA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sigB) != 0 {
|
||||
t.Errorf("should no signature")
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sigA) != 0 {
|
||||
t.Errorf("should no signature")
|
||||
}
|
||||
|
||||
key2, err := responder.ConfirmInitiator(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("got different key")
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix B
|
||||
func TestKeyExchangeSample(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
expectedPube := "9174542668e8f14ab273c0945c3690c66e5dd09678b86f734c4350567ed0628354e598c6bf749a3dacc9fffedd9db6866c50457cfc7aa2a4ad65c3168ff74210"
|
||||
expectedKey := "c5c13a8f59a97cdeae64f16a2272a9e7"
|
||||
expectedSignatureB := "3bb4bcee8139c960b4d6566db1e0d5f0b2767680e5e1bf934103e6c66e40ffee"
|
||||
expectedSignatureA := "195d1b7256ba7e0e67c71202a25f8c94ff8241702c2f55d613ae1c6b98215172"
|
||||
|
||||
kb, _ := hex.DecodeString("0002E65B0762D042F51F0D23542B13ED8CFA2E9A0E7206361E013A283905E31F")
|
||||
masterKey, err := NewEncryptMasterPrivateKey(kb)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(masterKey.MasterPublicKey.Marshal()) != expectedPube {
|
||||
t.Errorf("not expected master public key")
|
||||
}
|
||||
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := userKey.NewKeyExchange(userA, userB, 16, true)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := userKey.NewKeyExchange(userB, userA, 16, true)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
b, _ := hex.DecodeString("5879DD1D51E175946F23B1B41E93BA31C584AE59A426EC1046A4D03B06C8")
|
||||
k, err := bigmod.NewNat().SetBytes(b, orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initKeyExchange(initiator, hid, k)
|
||||
|
||||
if hex.EncodeToString(initiator.secret) != "047cba5b19069ee66aa79d490413d11846b9ba76dd22567f809cf23b6d964bb265a9760c99cb6f706343fed05637085864958d6c90902aba7d405fbedf7b781599" {
|
||||
t.Fatal("not same")
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
b, _ = hex.DecodeString("018B98C44BEF9F8537FB7D071B2C928B3BC65BD3D69E1EEE213564905634FE")
|
||||
k, err = bigmod.NewNat().SetBytes(b, orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rB, sigB, err := respondKeyExchange(responder, hid, k, initiator.secret)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(sigB) != expectedSignatureB {
|
||||
t.Errorf("not expected signature B")
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hex.EncodeToString(key1) != expectedKey {
|
||||
t.Errorf("not expected key %v\n", hex.EncodeToString(key1))
|
||||
}
|
||||
if hex.EncodeToString(sigA) != expectedSignatureA {
|
||||
t.Errorf("not expected signature A")
|
||||
}
|
||||
// B8
|
||||
key2, err := responder.ConfirmInitiator(sigA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hex.EncodeToString(key2) != expectedKey {
|
||||
t.Errorf("not expected key %v\n", hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
@ -622,7 +622,7 @@ func TestMarshalPrivateKey(t *testing.T) {
|
||||
t.Fatalf("%d: ParseSM9SignPrivateKey should return error", i)
|
||||
}
|
||||
|
||||
if sm9SignMasterPrivateKey.D.Cmp(decodedSM9SignMasterPrivateKey.D) != 0 {
|
||||
if !sm9SignMasterPrivateKey.Equal(decodedSM9SignMasterPrivateKey) {
|
||||
t.Fatalf("%d: Decoded key does not match original key", i)
|
||||
}
|
||||
|
||||
@ -642,7 +642,7 @@ func TestMarshalPrivateKey(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatalf("%d: ParseSM9SignMasterPrivateKey should return error", i)
|
||||
}
|
||||
if !sm9SignPrivateKey.PrivateKey.Equal(decodedSM9SignPrivateKey.PrivateKey) {
|
||||
if !sm9SignPrivateKey.Equal(decodedSM9SignPrivateKey) {
|
||||
t.Fatalf("%d: Decoded key does not match original key", i)
|
||||
}
|
||||
|
||||
@ -663,7 +663,7 @@ func TestMarshalPrivateKey(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatalf("%d: ParseSM9EncryptPrivateKey should return error", i)
|
||||
}
|
||||
if sm9EncMasterPrivateKey.D.Cmp(decodedSM9EncMasterPrivateKey.D) != 0 {
|
||||
if !sm9EncMasterPrivateKey.Equal(decodedSM9EncMasterPrivateKey) {
|
||||
t.Fatalf("%d: Decoded key does not match original key", i)
|
||||
}
|
||||
|
||||
@ -683,7 +683,7 @@ func TestMarshalPrivateKey(t *testing.T) {
|
||||
if err == nil {
|
||||
t.Fatalf("%d: ParseSM9EncryptMasterPrivateKey should return error", i)
|
||||
}
|
||||
if !sm9EncPrivateKey.PrivateKey.Equal(decodedSM9EncPrivateKey.PrivateKey) {
|
||||
if !sm9EncPrivateKey.Equal(decodedSM9EncPrivateKey) {
|
||||
t.Fatalf("%d: Decoded key does not match original key", i)
|
||||
}
|
||||
|
||||
|
491
sm9/sm9.go
491
sm9/sm9.go
@ -8,36 +8,13 @@ import (
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/bigmod"
|
||||
"github.com/emmansun/gmsm/internal/byteorder"
|
||||
"github.com/emmansun/gmsm/internal/randutil"
|
||||
"github.com/emmansun/gmsm/internal/subtle"
|
||||
"github.com/emmansun/gmsm/internal/sm9"
|
||||
"github.com/emmansun/gmsm/sm3"
|
||||
"github.com/emmansun/gmsm/sm9/bn256"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
"golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
// SM9 ASN.1 format reference: Information security technology - SM9 cryptographic algorithm application specification
|
||||
var (
|
||||
orderMinus2 []byte
|
||||
orderNat *bigmod.Modulus
|
||||
)
|
||||
|
||||
func init() {
|
||||
orderMinus2 = new(big.Int).Sub(bn256.Order, big.NewInt(2)).Bytes()
|
||||
orderNat, _ = bigmod.NewModulus(bn256.Order.Bytes())
|
||||
}
|
||||
|
||||
type hashMode byte
|
||||
|
||||
const (
|
||||
// hashmode used in h1: 0x01
|
||||
H1 hashMode = 1 + iota
|
||||
// hashmode used in h2: 0x02
|
||||
H2
|
||||
)
|
||||
|
||||
type encryptType byte
|
||||
|
||||
const (
|
||||
@ -48,70 +25,6 @@ const (
|
||||
ENC_TYPE_CFB encryptType = 8
|
||||
)
|
||||
|
||||
// hash implements H1(Z,n) or H2(Z,n) in sm9 algorithm.
|
||||
func hash(z []byte, h hashMode) *bigmod.Nat {
|
||||
md := sm3.New()
|
||||
var ha [64]byte
|
||||
var countBytes [4]byte
|
||||
var ct uint32 = 1
|
||||
|
||||
byteorder.BEPutUint32(countBytes[:], ct)
|
||||
md.Write([]byte{byte(h)})
|
||||
md.Write(z)
|
||||
md.Write(countBytes[:])
|
||||
copy(ha[:], md.Sum(nil))
|
||||
ct++
|
||||
md.Reset()
|
||||
|
||||
byteorder.BEPutUint32(countBytes[:], ct)
|
||||
md.Write([]byte{byte(h)})
|
||||
md.Write(z)
|
||||
md.Write(countBytes[:])
|
||||
copy(ha[sm3.Size:], md.Sum(nil))
|
||||
|
||||
return bigmod.NewNat().SetOverflowedBytes(ha[:40], orderNat)
|
||||
}
|
||||
|
||||
func hashH1(z []byte) *bigmod.Nat {
|
||||
return hash(z, H1)
|
||||
}
|
||||
|
||||
func hashH2(z []byte) *bigmod.Nat {
|
||||
return hash(z, H2)
|
||||
}
|
||||
|
||||
func randomScalar(rand io.Reader) (k *bigmod.Nat, err error) {
|
||||
k = bigmod.NewNat()
|
||||
for {
|
||||
b := make([]byte, orderNat.Size())
|
||||
if _, err = io.ReadFull(rand, b); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// Mask off any excess bits to increase the chance of hitting a value in
|
||||
// (0, N). These are the most dangerous lines in the package and maybe in
|
||||
// the library: a single bit of bias in the selection of nonces would likely
|
||||
// lead to key recovery, but no tests would fail. Look but DO NOT TOUCH.
|
||||
if excess := len(b)*8 - orderNat.BitLen(); excess > 0 {
|
||||
// Just to be safe, assert that this only happens for the one curve that
|
||||
// doesn't have a round number of bits.
|
||||
if excess != 0 {
|
||||
panic("sm9: internal error: unexpectedly masking off bits")
|
||||
}
|
||||
b[0] >>= excess
|
||||
}
|
||||
|
||||
// FIPS 186-4 makes us check k <= N - 2 and then add one.
|
||||
// Checking 0 < k <= N - 1 is strictly equivalent.
|
||||
// None of this matters anyway because the chance of selecting
|
||||
// zero is cryptographically negligible.
|
||||
if _, err = k.SetBytes(b, orderNat); err == nil && k.IsZero() == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Sign signs a hash (which should be the result of hashing a larger message)
|
||||
// using the user dsa key. It returns the signature as a pair of h and s.
|
||||
// Please use SignASN1 instead.
|
||||
@ -119,12 +32,13 @@ func randomScalar(rand io.Reader) (k *bigmod.Nat, err error) {
|
||||
// The signature is randomized. Most applications should use [crypto/rand.Reader]
|
||||
// as rand. Note that the returned signature does not depend deterministically on
|
||||
// the bytes read from rand, and may change between calls and/or between versions.
|
||||
func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *bn256.G1, err error) {
|
||||
sig, err := SignASN1(rand, priv, hash)
|
||||
func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (*big.Int, []byte, error) {
|
||||
h, s, err := priv.privateKey.Sign(rand, hash, nil)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return parseSignatureLegacy(sig)
|
||||
return new(big.Int).SetBytes(h), s, nil
|
||||
|
||||
}
|
||||
|
||||
// Sign signs digest with user's DSA key, reading randomness from rand. The opts argument
|
||||
@ -135,7 +49,11 @@ func Sign(rand io.Reader, priv *SignPrivateKey, hash []byte) (h *big.Int, s *bn2
|
||||
// as rand. Note that the returned signature does not depend deterministically on
|
||||
// the bytes read from rand, and may change between calls and/or between versions.
|
||||
func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.SignerOpts) ([]byte, error) {
|
||||
return SignASN1(rand, priv, hash)
|
||||
h, s, err := priv.privateKey.Sign(rand, hash, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return encodeSignature(h, s)
|
||||
}
|
||||
|
||||
// SignASN1 signs a hash (which should be the result of hashing a larger message)
|
||||
@ -145,63 +63,28 @@ func (priv *SignPrivateKey) Sign(rand io.Reader, hash []byte, opts crypto.Signer
|
||||
// as rand. Note that the returned signature does not depend deterministically on
|
||||
// the bytes read from rand, and may change between calls and/or between versions.
|
||||
func SignASN1(rand io.Reader, priv *SignPrivateKey, hash []byte) ([]byte, error) {
|
||||
var (
|
||||
hNat *bigmod.Nat
|
||||
s *bn256.G1
|
||||
)
|
||||
randutil.MaybeReadByte(rand)
|
||||
for {
|
||||
r, err := randomScalar(rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
w, err := priv.SignMasterPublicKey.ScalarBaseMult(r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, hash...), w.Marshal()...)
|
||||
|
||||
hNat = hashH2(buffer)
|
||||
r.Sub(hNat, orderNat)
|
||||
|
||||
if r.IsZero() == 0 {
|
||||
s, err = new(bn256.G1).ScalarMult(priv.PrivateKey, r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return encodeSignature(hNat.Bytes(orderNat), s)
|
||||
return priv.Sign(rand, hash, nil)
|
||||
}
|
||||
|
||||
// Verify verifies the signature in h, s of hash using the master dsa public key and user id, uid and hid.
|
||||
// Its return value records whether the signature is valid. Please use VerifyASN1 instead.
|
||||
func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big.Int, s *bn256.G1) bool {
|
||||
func Verify(pub *SignMasterPublicKey, uid []byte, hid byte, hash []byte, h *big.Int, s []byte) bool {
|
||||
if h.Sign() <= 0 {
|
||||
return false
|
||||
}
|
||||
sig, err := encodeSignature(h.Bytes(), s)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return VerifyASN1(pub, uid, hid, hash, sig)
|
||||
return pub.publicKey.Verify(uid, hid, hash, h.Bytes(), s)
|
||||
}
|
||||
|
||||
func encodeSignature(hBytes []byte, s *bn256.G1) ([]byte, error) {
|
||||
func encodeSignature(h, s []byte) ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1OctetString(hBytes)
|
||||
b.AddASN1BitString(s.MarshalUncompressed())
|
||||
b.AddASN1OctetString(h)
|
||||
b.AddASN1BitString(s)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func parseSignature(sig []byte) ([]byte, *bn256.G1, error) {
|
||||
func parseSignature(sig []byte) ([]byte, []byte, error) {
|
||||
var (
|
||||
hBytes []byte
|
||||
sBytes []byte
|
||||
@ -218,20 +101,7 @@ func parseSignature(sig []byte) ([]byte, *bn256.G1, error) {
|
||||
if sBytes[0] != 4 {
|
||||
return nil, nil, errors.New("sm9: invalid point format")
|
||||
}
|
||||
s := new(bn256.G1)
|
||||
_, err := s.Unmarshal(sBytes[1:])
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return hBytes, s, nil
|
||||
}
|
||||
|
||||
func parseSignatureLegacy(sig []byte) (*big.Int, *bn256.G1, error) {
|
||||
hBytes, s, err := parseSignature(sig)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return new(big.Int).SetBytes(hBytes), s, nil
|
||||
return hBytes, sBytes, nil
|
||||
}
|
||||
|
||||
// VerifyASN1 verifies the ASN.1 encoded signature of type SM9Signature, sig, of hash using the
|
||||
@ -241,34 +111,7 @@ func VerifyASN1(pub *SignMasterPublicKey, uid []byte, hid byte, hash, sig []byte
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if !s.IsOnCurve() {
|
||||
return false
|
||||
}
|
||||
|
||||
hNat, err := bigmod.NewNat().SetBytes(h, orderNat)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
if hNat.IsZero() == 1 {
|
||||
return false
|
||||
}
|
||||
|
||||
t, err := pub.ScalarBaseMult(hNat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
// user sign public key p generation
|
||||
p := pub.GenerateUserPublicKey(uid, hid)
|
||||
|
||||
u := bn256.Pair(s, p)
|
||||
w := new(bn256.GT).Add(u, t)
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, hash...), w.Marshal()...)
|
||||
h2 := hashH2(buffer)
|
||||
|
||||
return h2.Equal(hNat) == 1
|
||||
return pub.publicKey.Verify(uid, hid, hash, h, s)
|
||||
}
|
||||
|
||||
// Verify verifies the ASN.1 encoded signature, sig, of hash using the
|
||||
@ -282,39 +125,8 @@ func (pub *SignMasterPublicKey) Verify(uid []byte, hid byte, hash, sig []byte) b
|
||||
// The rand parameter is used as a source of entropy to ensure that
|
||||
// calls this function twice doesn't result in the same key.
|
||||
// Most applications should use [crypto/rand.Reader] as random.
|
||||
func WrapKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, kLen int) (key []byte, cipher *bn256.G1, err error) {
|
||||
q := pub.GenerateUserPublicKey(uid, hid)
|
||||
var (
|
||||
r *bigmod.Nat
|
||||
w *bn256.GT
|
||||
)
|
||||
for {
|
||||
r, err = randomScalar(rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rBytes := r.Bytes(orderNat)
|
||||
cipher, err = new(bn256.G1).ScalarMult(q, rBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
w, err = pub.ScalarBaseMult(rBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
var buffer []byte
|
||||
buffer = append(buffer, cipher.Marshal()...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
buffer = append(buffer, uid...)
|
||||
|
||||
key = sm3.Kdf(buffer, kLen)
|
||||
if subtle.ConstantTimeAllZero(key) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return
|
||||
func WrapKey(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte, kLen int) ([]byte, []byte, error) {
|
||||
return pub.publicKey.WrapKey(rand, uid, hid, kLen)
|
||||
}
|
||||
|
||||
// WrapKey wraps key and converts the cipher as ASN1 format, SM9PublicKey1 definition.
|
||||
@ -328,7 +140,7 @@ func (pub *EncryptMasterPublicKey) WrapKey(rand io.Reader, uid []byte, hid byte,
|
||||
return nil, nil, err
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(cipher.MarshalUncompressed())
|
||||
b.AddASN1BitString(cipher)
|
||||
cipherASN1, err := b.Bytes()
|
||||
|
||||
return key, cipherASN1, err
|
||||
@ -348,31 +160,25 @@ func (pub *EncryptMasterPublicKey) WrapKeyASN1(rand io.Reader, uid []byte, hid b
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1OctetString(key)
|
||||
b.AddASN1BitString(cipher.MarshalUncompressed())
|
||||
b.AddASN1BitString(cipher)
|
||||
})
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// UnmarshalSM9KeyPackage is an utility to unmarshal SM9KeyPackage
|
||||
func UnmarshalSM9KeyPackage(der []byte) ([]byte, *bn256.G1, error) {
|
||||
func UnmarshalSM9KeyPackage(der []byte) (key []byte, cipher []byte, err error) {
|
||||
input := cryptobyte.String(der)
|
||||
var (
|
||||
key []byte
|
||||
cipherBytes []byte
|
||||
inner cryptobyte.String
|
||||
)
|
||||
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
|
||||
!input.Empty() ||
|
||||
!inner.ReadASN1Bytes(&key, asn1.OCTET_STRING) ||
|
||||
!inner.ReadASN1BitStringAsBytes(&cipherBytes) ||
|
||||
!inner.ReadASN1BitStringAsBytes(&cipher) ||
|
||||
!inner.Empty() {
|
||||
return nil, nil, errors.New("sm9: invalid SM9KeyPackage asn.1 data")
|
||||
}
|
||||
g, err := unmarshalG1(cipherBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return key, g, nil
|
||||
return
|
||||
}
|
||||
|
||||
// ErrDecryption represents a failure to decrypt a message.
|
||||
@ -383,23 +189,8 @@ var ErrDecryption = errors.New("sm9: decryption error")
|
||||
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
|
||||
}
|
||||
|
||||
w := bn256.Pair(cipher, priv.PrivateKey)
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(buffer, cipher.Marshal()...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
buffer = append(buffer, uid...)
|
||||
|
||||
key := sm3.Kdf(buffer, kLen)
|
||||
if subtle.ConstantTimeAllZero(key) == 1 {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
return key, nil
|
||||
func UnwrapKey(priv *EncryptPrivateKey, uid, cipher []byte, kLen int) ([]byte, error) {
|
||||
return priv.privateKey.UnwrapKey(uid, cipher, kLen)
|
||||
}
|
||||
|
||||
// UnwrapKey unwraps key from cipherDer, user id and aligned key length.
|
||||
@ -410,11 +201,7 @@ func (priv *EncryptPrivateKey) UnwrapKey(uid, cipherDer []byte, kLen int) ([]byt
|
||||
if !input.ReadASN1BitStringAsBytes(&bytes) || !input.Empty() {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
g, err := unmarshalG1(bytes)
|
||||
if err != nil {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
return UnwrapKey(priv, uid, g, kLen)
|
||||
return UnwrapKey(priv, uid, bytes, kLen)
|
||||
}
|
||||
|
||||
// Encrypt encrypts plaintext, returns ciphertext with format C1||C3||C2.
|
||||
@ -423,12 +210,12 @@ func Encrypt(rand io.Reader, pub *EncryptMasterPublicKey, uid []byte, hid byte,
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ciphertext := append(c1.Marshal(), c3...)
|
||||
ciphertext := append(c1[1:], c3...)
|
||||
ciphertext = append(ciphertext, c2...)
|
||||
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, c2, c3 []byte, err error) {
|
||||
if opts == nil {
|
||||
opts = DefaultEncrypterOpts
|
||||
}
|
||||
@ -473,7 +260,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.GetEncryptType()))
|
||||
b.AddASN1BitString(c1.MarshalUncompressed())
|
||||
b.AddASN1BitString(c1)
|
||||
b.AddASN1OctetString(c3)
|
||||
b.AddASN1OctetString(c2)
|
||||
})
|
||||
@ -486,26 +273,21 @@ func Decrypt(priv *EncryptPrivateKey, uid, ciphertext []byte, opts EncrypterOpts
|
||||
opts = DefaultEncrypterOpts
|
||||
}
|
||||
|
||||
c := &bn256.G1{}
|
||||
c3c2, err := c.Unmarshal(ciphertext)
|
||||
if err != nil {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
|
||||
_ = c3c2[sm3.Size] // bounds check elimination hint
|
||||
c1 := ciphertext[:64]
|
||||
c3c2 := ciphertext[64:]
|
||||
c3 := c3c2[:sm3.Size]
|
||||
c2 := c3c2[sm3.Size:]
|
||||
key1Len := opts.GetKeySize(c2)
|
||||
|
||||
key, err := UnwrapKey(priv, uid, c, key1Len+sm3.Size)
|
||||
key, err := UnwrapKey(priv, uid, c1, key1Len+sm3.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = key[key1Len] // bounds check elimination hint
|
||||
return decrypt(c, key[:key1Len], key[key1Len:], c2, c3, opts)
|
||||
return decrypt(key[:key1Len], key[key1Len:], c2, c3, opts)
|
||||
}
|
||||
|
||||
func decrypt(cipher *bn256.G1, key1, key2, c2, c3 []byte, opts EncrypterOpts) ([]byte, error) {
|
||||
func decrypt(key1, key2, c2, c3 []byte, opts EncrypterOpts) ([]byte, error) {
|
||||
hash := sm3.New()
|
||||
hash.Write(c2)
|
||||
hash.Write(key2)
|
||||
@ -546,19 +328,14 @@ func DecryptASN1(priv *EncryptPrivateKey, uid, ciphertext []byte) ([]byte, error
|
||||
if opts == nil {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
c, err := unmarshalG1(c1Bytes)
|
||||
if err != nil {
|
||||
return nil, ErrDecryption
|
||||
}
|
||||
|
||||
key1Len := opts.GetKeySize(c2Bytes)
|
||||
key, err := UnwrapKey(priv, uid, c, key1Len+sm3.Size)
|
||||
key, err := UnwrapKey(priv, uid, c1Bytes, key1Len+sm3.Size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_ = key[key1Len] // bounds check elimination hint
|
||||
return decrypt(c, key[:key1Len], key[key1Len:], c2Bytes, c3Bytes, opts)
|
||||
return decrypt(key[:key1Len], key[key1Len:], c2Bytes, c3Bytes, opts)
|
||||
}
|
||||
|
||||
// Decrypt decrypts chipher, the ciphertext should be with format C1||C3||C2
|
||||
@ -576,197 +353,33 @@ func (priv *EncryptPrivateKey) DecryptASN1(uid, ciphertext []byte) ([]byte, erro
|
||||
// Initiator's flow will be: NewKeyExchange -> InitKeyExchange -> transmission -> ConfirmResponder
|
||||
// Responder's flow will be: NewKeyExchange -> waiting ... -> RepondKeyExchange -> transmission -> ConfirmInitiator
|
||||
type KeyExchange struct {
|
||||
genSignature bool // control the optional sign/verify step triggered by responsder
|
||||
keyLength int // key length
|
||||
privateKey *EncryptPrivateKey // owner's encryption private key
|
||||
uid []byte // owner uid
|
||||
peerUID []byte // peer uid
|
||||
r *bigmod.Nat // random which will be used to compute secret
|
||||
secret *bn256.G1 // generated secret which will be passed to peer
|
||||
peerSecret *bn256.G1 // received peer's secret
|
||||
g1 *bn256.GT // internal state which will be used when compute the key and signature
|
||||
g2 *bn256.GT // internal state which will be used when compute the key and signature
|
||||
g3 *bn256.GT // internal state which will be used when compute the key and signature
|
||||
ke *sm9.KeyExchange
|
||||
}
|
||||
|
||||
// NewKeyExchange creates one new KeyExchange object
|
||||
func NewKeyExchange(priv *EncryptPrivateKey, uid, peerUID []byte, keyLen int, genSignature bool) *KeyExchange {
|
||||
ke := &KeyExchange{}
|
||||
ke.genSignature = genSignature
|
||||
ke.keyLength = keyLen
|
||||
ke.privateKey = priv
|
||||
ke.uid = uid
|
||||
ke.peerUID = peerUID
|
||||
return ke
|
||||
func (priv *EncryptPrivateKey) NewKeyExchange(uid, peerUID []byte, keyLen int, genSignature bool) *KeyExchange {
|
||||
return &KeyExchange{ke: priv.privateKey.NewKeyExchange(uid, peerUID, keyLen, genSignature)}
|
||||
}
|
||||
|
||||
// Destroy clears all internal state and Ephemeral private/public keys
|
||||
func (ke *KeyExchange) Destroy() {
|
||||
if ke.r != nil {
|
||||
ke.r.SetBytes([]byte{0}, orderNat)
|
||||
}
|
||||
if ke.g1 != nil {
|
||||
ke.g1.SetOne()
|
||||
}
|
||||
if ke.g2 != nil {
|
||||
ke.g2.SetOne()
|
||||
}
|
||||
if ke.g3 != nil {
|
||||
ke.g3.SetOne()
|
||||
}
|
||||
}
|
||||
|
||||
func initKeyExchange(ke *KeyExchange, hid byte, r *bigmod.Nat) {
|
||||
pubB := ke.privateKey.GenerateUserPublicKey(ke.peerUID, hid)
|
||||
ke.r = r
|
||||
rA, err := new(bn256.G1).ScalarMult(pubB, ke.r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
ke.secret = rA
|
||||
ke.ke.Destroy()
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return nil, err
|
||||
}
|
||||
initKeyExchange(ke, hid, r)
|
||||
return ke.secret, nil
|
||||
func (ke *KeyExchange) InitKeyExchange(rand io.Reader, hid byte) ([]byte, error) {
|
||||
return ke.ke.InitKeyExchange(rand, hid)
|
||||
}
|
||||
|
||||
func (ke *KeyExchange) sign(isResponder bool, prefix byte) []byte {
|
||||
var buffer []byte
|
||||
hash := sm3.New()
|
||||
hash.Write(ke.g2.Marshal())
|
||||
hash.Write(ke.g3.Marshal())
|
||||
if isResponder {
|
||||
hash.Write(ke.peerUID)
|
||||
hash.Write(ke.uid)
|
||||
hash.Write(ke.peerSecret.Marshal())
|
||||
hash.Write(ke.secret.Marshal())
|
||||
} else {
|
||||
hash.Write(ke.uid)
|
||||
hash.Write(ke.peerUID)
|
||||
hash.Write(ke.secret.Marshal())
|
||||
hash.Write(ke.peerSecret.Marshal())
|
||||
}
|
||||
buffer = hash.Sum(nil)
|
||||
hash.Reset()
|
||||
hash.Write([]byte{prefix})
|
||||
hash.Write(ke.g1.Marshal())
|
||||
hash.Write(buffer)
|
||||
return hash.Sum(nil)
|
||||
}
|
||||
|
||||
func (ke *KeyExchange) generateSharedKey(isResponder bool) ([]byte, error) {
|
||||
var buffer []byte
|
||||
if isResponder {
|
||||
buffer = append(buffer, ke.peerUID...)
|
||||
buffer = append(buffer, ke.uid...)
|
||||
buffer = append(buffer, ke.peerSecret.Marshal()...)
|
||||
buffer = append(buffer, ke.secret.Marshal()...)
|
||||
} else {
|
||||
buffer = append(buffer, ke.uid...)
|
||||
buffer = append(buffer, ke.peerUID...)
|
||||
buffer = append(buffer, ke.secret.Marshal()...)
|
||||
buffer = append(buffer, ke.peerSecret.Marshal()...)
|
||||
}
|
||||
buffer = append(buffer, ke.g1.Marshal()...)
|
||||
buffer = append(buffer, ke.g2.Marshal()...)
|
||||
buffer = append(buffer, ke.g3.Marshal()...)
|
||||
|
||||
return sm3.Kdf(buffer, ke.keyLength), nil
|
||||
}
|
||||
|
||||
func respondKeyExchange(ke *KeyExchange, hid byte, r *bigmod.Nat, rA *bn256.G1) (*bn256.G1, []byte, error) {
|
||||
if !rA.IsOnCurve() {
|
||||
return nil, nil, errors.New("sm9: invalid initiator's ephemeral public key")
|
||||
}
|
||||
ke.peerSecret = rA
|
||||
pubA := ke.privateKey.GenerateUserPublicKey(ke.peerUID, hid)
|
||||
ke.r = r
|
||||
rBytes := r.Bytes(orderNat)
|
||||
rB, err := new(bn256.G1).ScalarMult(pubA, rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.secret = rB
|
||||
|
||||
ke.g1 = bn256.Pair(ke.peerSecret, ke.privateKey.PrivateKey)
|
||||
ke.g3 = &bn256.GT{}
|
||||
g3, err := bn256.ScalarMultGT(ke.g1, rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g3 = g3
|
||||
|
||||
g2, err := ke.privateKey.EncryptMasterPublicKey.ScalarBaseMult(rBytes)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g2 = g2
|
||||
|
||||
if !ke.genSignature {
|
||||
return ke.secret, nil, nil
|
||||
}
|
||||
|
||||
return ke.secret, ke.sign(true, 0x82), nil
|
||||
}
|
||||
|
||||
// RepondKeyExchange when responder receive rA, for responder's step B1-B7
|
||||
func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, hid byte, rA *bn256.G1) (*bn256.G1, []byte, error) {
|
||||
r, err := randomScalar(rand)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
return respondKeyExchange(ke, hid, r, rA)
|
||||
// RespondKeyExchange when responder receive rA, for responder's step B1-B7
|
||||
func (ke *KeyExchange) RespondKeyExchange(rand io.Reader, hid byte, peerData []byte) ([]byte, []byte, error) {
|
||||
return ke.ke.RespondKeyExchange(rand, hid, peerData)
|
||||
}
|
||||
|
||||
// ConfirmResponder for initiator's step A5-A7
|
||||
func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, []byte, error) {
|
||||
if !rB.IsOnCurve() {
|
||||
return nil, nil, errors.New("sm9: invalid responder's ephemeral public key")
|
||||
}
|
||||
// step 5
|
||||
ke.peerSecret = rB
|
||||
g1, err := ke.privateKey.EncryptMasterPublicKey.ScalarBaseMult(ke.r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g1 = g1
|
||||
ke.g2 = bn256.Pair(ke.peerSecret, ke.privateKey.PrivateKey)
|
||||
ke.g3 = &bn256.GT{}
|
||||
g3, err := bn256.ScalarMultGT(ke.g2, ke.r.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
ke.g3 = g3
|
||||
// step 6, verify signature
|
||||
if len(sB) > 0 {
|
||||
signature := ke.sign(false, 0x82)
|
||||
if goSubtle.ConstantTimeCompare(signature, sB) != 1 {
|
||||
return nil, nil, errors.New("sm9: invalid responder's signature")
|
||||
}
|
||||
}
|
||||
key, err := ke.generateSharedKey(false)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
if !ke.genSignature {
|
||||
return key, nil, nil
|
||||
}
|
||||
return key, ke.sign(false, 0x83), nil
|
||||
func (ke *KeyExchange) ConfirmResponder(rB, sB []byte) ([]byte, []byte, error) {
|
||||
return ke.ke.ConfirmResponder(rB, sB)
|
||||
}
|
||||
|
||||
// ConfirmInitiator for responder's step B8
|
||||
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) ([]byte, error) {
|
||||
if s1 != nil {
|
||||
buffer := ke.sign(true, 0x83)
|
||||
if goSubtle.ConstantTimeCompare(buffer, s1) != 1 {
|
||||
return nil, errors.New("sm9: invalid initiator's signature")
|
||||
}
|
||||
}
|
||||
return ke.generateSharedKey(true)
|
||||
func (ke *KeyExchange) ConfirmInitiator(peerData []byte) ([]byte, error) {
|
||||
return ke.ke.ConfirmInitiator(peerData)
|
||||
}
|
||||
|
344
sm9/sm9_key.go
344
sm9/sm9_key.go
@ -6,80 +6,69 @@ import (
|
||||
"errors"
|
||||
"io"
|
||||
"math/big"
|
||||
"sync"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/bigmod"
|
||||
"github.com/emmansun/gmsm/sm9/bn256"
|
||||
"github.com/emmansun/gmsm/internal/sm9"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
cryptobyte_asn1 "golang.org/x/crypto/cryptobyte/asn1"
|
||||
)
|
||||
|
||||
// SignMasterPrivateKey master private key for sign, generated by KGC
|
||||
type SignMasterPrivateKey struct {
|
||||
*SignMasterPublicKey // master public key
|
||||
D *big.Int // master private key
|
||||
privateKey *sm9.SignMasterPrivateKey
|
||||
}
|
||||
|
||||
// SignMasterPublicKey master public key for sign, generated by KGC
|
||||
type SignMasterPublicKey struct {
|
||||
MasterPublicKey *bn256.G2 // master public key
|
||||
pairOnce sync.Once
|
||||
basePoint *bn256.GT // the result of Pair(Gen1, pub.MasterPublicKey)
|
||||
tableGenOnce sync.Once
|
||||
table *[32 * 2]bn256.GTFieldTable // precomputed basePoint^n
|
||||
publicKey *sm9.SignMasterPublicKey
|
||||
}
|
||||
|
||||
// SignPrivateKey user private key for sign, generated by KGC
|
||||
type SignPrivateKey struct {
|
||||
PrivateKey *bn256.G1 // user private key
|
||||
*SignMasterPublicKey // master public key
|
||||
privateKey *sm9.SignPrivateKey
|
||||
}
|
||||
|
||||
// EncryptMasterPrivateKey master private key for encryption, generated by KGC
|
||||
type EncryptMasterPrivateKey struct {
|
||||
*EncryptMasterPublicKey // master public key
|
||||
D *big.Int // master private key
|
||||
privateKey *sm9.EncryptMasterPrivateKey
|
||||
}
|
||||
|
||||
// EncryptMasterPublicKey master private key for encryption, generated by KGC
|
||||
type EncryptMasterPublicKey struct {
|
||||
MasterPublicKey *bn256.G1 // public key
|
||||
pairOnce sync.Once
|
||||
basePoint *bn256.GT // the result of Pair(pub.MasterPublicKey, Gen2)
|
||||
tableGenOnce sync.Once
|
||||
table *[32 * 2]bn256.GTFieldTable // precomputed basePoint^n
|
||||
publicKey *sm9.EncryptMasterPublicKey
|
||||
}
|
||||
|
||||
// EncryptPrivateKey user private key for encryption, generated by KGC
|
||||
type EncryptPrivateKey struct {
|
||||
PrivateKey *bn256.G2 // user private key
|
||||
*EncryptMasterPublicKey // master public key
|
||||
privateKey *sm9.EncryptPrivateKey
|
||||
}
|
||||
|
||||
// GenerateSignMasterKey generates a master public and private key pair for DSA usage.
|
||||
func GenerateSignMasterKey(rand io.Reader) (*SignMasterPrivateKey, error) {
|
||||
k, err := randomScalar(rand)
|
||||
priv, err := sm9.GenerateSignMasterKey(rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kBytes := k.Bytes(orderNat)
|
||||
p, err := new(bn256.G2).ScalarBaseMult(kBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return &SignMasterPrivateKey{privateKey: priv}, nil
|
||||
}
|
||||
|
||||
priv := new(SignMasterPrivateKey)
|
||||
priv.D = new(big.Int).SetBytes(kBytes)
|
||||
priv.SignMasterPublicKey = new(SignMasterPublicKey)
|
||||
priv.MasterPublicKey = p
|
||||
return priv, nil
|
||||
// Equal compares the receiver SignMasterPrivateKey with another SignMasterPrivateKey
|
||||
// and returns true if they are equal, otherwise it returns false.
|
||||
func (master *SignMasterPrivateKey) Equal(x *SignMasterPrivateKey) bool {
|
||||
return master.privateKey.Equal(x.privateKey)
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the SignMasterPrivateKey.
|
||||
// It converts the private key to a byte slice.
|
||||
func (master *SignMasterPrivateKey) Bytes() []byte {
|
||||
return master.privateKey.Bytes()
|
||||
}
|
||||
|
||||
// MarshalASN1 marshal sign master private key to asn.1 format data according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
func (master *SignMasterPrivateKey) MarshalASN1() ([]byte, error) {
|
||||
d := new(big.Int).SetBytes(master.privateKey.Bytes())
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(master.D)
|
||||
b.AddASN1BigInt(d)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -89,6 +78,7 @@ func (master *SignMasterPrivateKey) UnmarshalASN1(der []byte) error {
|
||||
d := &big.Int{}
|
||||
var inner cryptobyte.String
|
||||
var pubBytes []byte
|
||||
var err error
|
||||
if der[0] == 0x30 {
|
||||
if !input.ReadASN1(&inner, cryptobyte_asn1.SEQUENCE) ||
|
||||
!input.Empty() ||
|
||||
@ -102,92 +92,44 @@ func (master *SignMasterPrivateKey) UnmarshalASN1(der []byte) error {
|
||||
} else if !input.ReadASN1Integer(d) || !input.Empty() {
|
||||
return errors.New("sm9: invalid sign master private key asn1 data")
|
||||
}
|
||||
master.D = d
|
||||
master.SignMasterPublicKey = new(SignMasterPublicKey)
|
||||
p, err := new(bn256.G2).ScalarBaseMult(bn256.NormalizeScalar(d.Bytes()))
|
||||
master.privateKey, err = sm9.NewSignMasterPrivateKey(d.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
master.MasterPublicKey = p
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenerateUserKey generate an user dsa key.
|
||||
func (master *SignMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*SignPrivateKey, error) {
|
||||
var id []byte
|
||||
id = append(append(id, uid...), hid)
|
||||
|
||||
t1Nat := hashH1(id)
|
||||
|
||||
d, err := bigmod.NewNat().SetBytes(master.D.Bytes(), orderNat)
|
||||
priv, err := master.privateKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t1Nat.Add(d, orderNat)
|
||||
if t1Nat.IsZero() == 1 {
|
||||
return nil, errors.New("sm9: need to re-generate sign master private key")
|
||||
}
|
||||
|
||||
t1Nat = bigmod.NewNat().Exp(t1Nat, orderMinus2, orderNat)
|
||||
t1Nat.Mul(d, orderNat)
|
||||
|
||||
priv := new(SignPrivateKey)
|
||||
priv.SignMasterPublicKey = master.SignMasterPublicKey
|
||||
g1, err := new(bn256.G1).ScalarBaseMult(t1Nat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
priv.PrivateKey = g1
|
||||
|
||||
return priv, nil
|
||||
return &SignPrivateKey{privateKey: priv}, nil
|
||||
}
|
||||
|
||||
// Public returns the public key corresponding to priv.
|
||||
func (master *SignMasterPrivateKey) Public() *SignMasterPublicKey {
|
||||
return master.SignMasterPublicKey
|
||||
return &SignMasterPublicKey{master.privateKey.Public()}
|
||||
}
|
||||
|
||||
// pair generate the basepoint once
|
||||
func (pub *SignMasterPublicKey) pair() *bn256.GT {
|
||||
pub.pairOnce.Do(func() {
|
||||
pub.basePoint = bn256.Pair(bn256.Gen1, pub.MasterPublicKey)
|
||||
})
|
||||
return pub.basePoint
|
||||
// Equal compares the receiver SignMasterPublicKey with another SignMasterPublicKey
|
||||
// and returns true if they are equal, otherwise false.
|
||||
func (pub *SignMasterPublicKey) Equal(x *SignMasterPublicKey) bool {
|
||||
return pub.publicKey.Equal(x.publicKey)
|
||||
}
|
||||
|
||||
func (pub *SignMasterPublicKey) generatorTable() *[32 * 2]bn256.GTFieldTable {
|
||||
pub.tableGenOnce.Do(func() {
|
||||
pub.table = bn256.GenerateGTFieldTable(pub.pair())
|
||||
})
|
||||
return pub.table
|
||||
}
|
||||
|
||||
// ScalarBaseMult compute basepoint^r with precomputed table
|
||||
// The base point = pair(Gen1, <master public key>)
|
||||
func (pub *SignMasterPublicKey) ScalarBaseMult(scalar []byte) (*bn256.GT, error) {
|
||||
tables := pub.generatorTable()
|
||||
return bn256.ScalarBaseMultGT(tables, scalar)
|
||||
}
|
||||
|
||||
// GenerateUserPublicKey generate user sign public key
|
||||
func (pub *SignMasterPublicKey) GenerateUserPublicKey(uid []byte, hid byte) *bn256.G2 {
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, uid...), hid)
|
||||
h1 := hashH1(buffer)
|
||||
p, err := new(bn256.G2).ScalarBaseMult(h1.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.Add(p, pub.MasterPublicKey)
|
||||
return p
|
||||
// Bytes returns the byte representation of the SignMasterPublicKey.
|
||||
// It calls the Bytes method on the underlying publicKey field.
|
||||
func (pub *SignMasterPublicKey) Bytes() []byte {
|
||||
return pub.publicKey.Bytes()
|
||||
}
|
||||
|
||||
// MarshalASN1 marshal sign master public key to asn.1 format data according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
func (pub *SignMasterPublicKey) MarshalASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(pub.MasterPublicKey.MarshalUncompressed())
|
||||
b.AddASN1BitString(pub.publicKey.MasterPublicKey.MarshalUncompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -195,37 +137,16 @@ func (pub *SignMasterPublicKey) MarshalASN1() ([]byte, error) {
|
||||
// SM9 cryptographic algorithm application specification, the curve point is in compressed form.
|
||||
func (pub *SignMasterPublicKey) MarshalCompressedASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(pub.MasterPublicKey.MarshalCompressed())
|
||||
b.AddASN1BitString(pub.publicKey.MasterPublicKey.MarshalCompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func unmarshalG2(bytes []byte) (*bn256.G2, error) {
|
||||
g2 := new(bn256.G2)
|
||||
switch bytes[0] {
|
||||
case 4:
|
||||
_, err := g2.Unmarshal(bytes[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 2, 3:
|
||||
_, err := g2.UnmarshalCompressed(bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("sm9: invalid point identity byte")
|
||||
}
|
||||
return g2, nil
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to sign master public key
|
||||
func (pub *SignMasterPublicKey) UnmarshalRaw(bytes []byte) error {
|
||||
g2, err := unmarshalG2(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
if pub.publicKey == nil {
|
||||
pub.publicKey = new(sm9.SignMasterPublicKey)
|
||||
}
|
||||
pub.MasterPublicKey = g2
|
||||
return nil
|
||||
return pub.publicKey.UnmarshalRaw(bytes)
|
||||
}
|
||||
|
||||
// UnmarshalASN1 unmarsal der data to sign master public key
|
||||
@ -255,23 +176,29 @@ func (pub *SignMasterPublicKey) ParseFromPEM(data []byte) error {
|
||||
return pub.UnmarshalASN1(block.Bytes)
|
||||
}
|
||||
|
||||
func (priv *SignPrivateKey) Equal(x *SignPrivateKey) bool {
|
||||
return priv.privateKey.Equal(x.privateKey)
|
||||
}
|
||||
|
||||
func (priv *SignPrivateKey) Bytes() []byte {
|
||||
return priv.privateKey.Bytes()
|
||||
}
|
||||
|
||||
// MasterPublic returns the master public key corresponding to priv.
|
||||
func (priv *SignPrivateKey) MasterPublic() *SignMasterPublicKey {
|
||||
return priv.SignMasterPublicKey
|
||||
return &SignMasterPublicKey{priv.privateKey.MasterPublic()}
|
||||
}
|
||||
|
||||
// SetMasterPublicKey bind the sign master public key to it.
|
||||
func (priv *SignPrivateKey) SetMasterPublicKey(pub *SignMasterPublicKey) {
|
||||
if priv.SignMasterPublicKey == nil || priv.SignMasterPublicKey.MasterPublicKey == nil {
|
||||
priv.SignMasterPublicKey = pub
|
||||
}
|
||||
priv.privateKey.SetMasterPublicKey(pub.publicKey)
|
||||
}
|
||||
|
||||
// MarshalASN1 marshal sign user private key to asn.1 format data according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
func (priv *SignPrivateKey) MarshalASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(priv.PrivateKey.MarshalUncompressed())
|
||||
b.AddASN1BitString(priv.privateKey.PrivateKey.MarshalUncompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -279,38 +206,17 @@ func (priv *SignPrivateKey) MarshalASN1() ([]byte, error) {
|
||||
// SM9 cryptographic algorithm application specification, the curve point is in compressed form.
|
||||
func (priv *SignPrivateKey) MarshalCompressedASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(priv.PrivateKey.MarshalCompressed())
|
||||
b.AddASN1BitString(priv.privateKey.PrivateKey.MarshalCompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
func unmarshalG1(bytes []byte) (*bn256.G1, error) {
|
||||
g := new(bn256.G1)
|
||||
switch bytes[0] {
|
||||
case 4:
|
||||
_, err := g.Unmarshal(bytes[1:])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
case 2, 3:
|
||||
_, err := g.UnmarshalCompressed(bytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
default:
|
||||
return nil, errors.New("sm9: invalid point identity byte")
|
||||
}
|
||||
return g, nil
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to sign user private key
|
||||
// Note, priv's SignMasterPublicKey should be handled separately.
|
||||
func (priv *SignPrivateKey) UnmarshalRaw(bytes []byte) error {
|
||||
g, err := unmarshalG1(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
if priv.privateKey == nil {
|
||||
priv.privateKey = new(sm9.SignPrivateKey)
|
||||
}
|
||||
priv.PrivateKey = g
|
||||
return nil
|
||||
return priv.privateKey.UnmarshalRaw(bytes)
|
||||
}
|
||||
|
||||
// UnmarshalASN1 unmarsal der data to sign user private key
|
||||
@ -349,64 +255,45 @@ func (priv *SignPrivateKey) UnmarshalASN1(der []byte) error {
|
||||
|
||||
// GenerateEncryptMasterKey generates a master public and private key pair for encryption usage.
|
||||
func GenerateEncryptMasterKey(rand io.Reader) (*EncryptMasterPrivateKey, error) {
|
||||
k, err := randomScalar(rand)
|
||||
priv, err := sm9.GenerateEncryptMasterKey(rand)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kBytes := k.Bytes(orderNat)
|
||||
|
||||
priv := new(EncryptMasterPrivateKey)
|
||||
priv.D = new(big.Int).SetBytes(kBytes)
|
||||
priv.EncryptMasterPublicKey = new(EncryptMasterPublicKey)
|
||||
p, err := new(bn256.G1).ScalarBaseMult(kBytes)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return &EncryptMasterPrivateKey{privateKey: priv}, nil
|
||||
}
|
||||
priv.MasterPublicKey = p
|
||||
return priv, nil
|
||||
|
||||
// Bytes returns the byte representation of the EncryptMasterPrivateKey.
|
||||
// It delegates the call to the Bytes method of the underlying privateKey.
|
||||
func (master *EncryptMasterPrivateKey) Bytes() []byte {
|
||||
return master.privateKey.Bytes()
|
||||
}
|
||||
|
||||
// Equal compares the receiver EncryptMasterPrivateKey with another EncryptMasterPrivateKey
|
||||
// and returns true if they are equal, otherwise it returns false.
|
||||
func (master *EncryptMasterPrivateKey) Equal(x *EncryptMasterPrivateKey) bool {
|
||||
return master.privateKey.Equal(x.privateKey)
|
||||
}
|
||||
|
||||
// GenerateUserKey generate an user key for encryption.
|
||||
func (master *EncryptMasterPrivateKey) GenerateUserKey(uid []byte, hid byte) (*EncryptPrivateKey, error) {
|
||||
var id []byte
|
||||
id = append(append(id, uid...), hid)
|
||||
|
||||
t1Nat := hashH1(id)
|
||||
|
||||
d, err := bigmod.NewNat().SetBytes(master.D.Bytes(), orderNat)
|
||||
priv, err := master.privateKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
t1Nat.Add(d, orderNat)
|
||||
if t1Nat.IsZero() == 1 {
|
||||
return nil, errors.New("sm9: need to re-generate encrypt master private key")
|
||||
}
|
||||
|
||||
t1Nat = bigmod.NewNat().Exp(t1Nat, orderMinus2, orderNat)
|
||||
t1Nat.Mul(d, orderNat)
|
||||
|
||||
priv := new(EncryptPrivateKey)
|
||||
priv.EncryptMasterPublicKey = master.EncryptMasterPublicKey
|
||||
p, err := new(bn256.G2).ScalarBaseMult(t1Nat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
priv.PrivateKey = p
|
||||
|
||||
return priv, nil
|
||||
return &EncryptPrivateKey{privateKey: priv}, nil
|
||||
}
|
||||
|
||||
// Public returns the public key corresponding to priv.
|
||||
func (master *EncryptMasterPrivateKey) Public() *EncryptMasterPublicKey {
|
||||
return master.EncryptMasterPublicKey
|
||||
return &EncryptMasterPublicKey{publicKey: master.privateKey.Public()}
|
||||
}
|
||||
|
||||
// MarshalASN1 marshal encrypt master private key to asn.1 format data according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
func (master *EncryptMasterPrivateKey) MarshalASN1() ([]byte, error) {
|
||||
d := new(big.Int).SetBytes(master.privateKey.Bytes())
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(master.D)
|
||||
b.AddASN1BigInt(d)
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -429,56 +316,31 @@ func (master *EncryptMasterPrivateKey) UnmarshalASN1(der []byte) error {
|
||||
} else if !input.ReadASN1Integer(d) || !input.Empty() {
|
||||
return errors.New("sm9: invalid encrypt master private key asn1 data")
|
||||
}
|
||||
master.D = d
|
||||
master.EncryptMasterPublicKey = new(EncryptMasterPublicKey)
|
||||
p, err := new(bn256.G1).ScalarBaseMult(bn256.NormalizeScalar(d.Bytes()))
|
||||
var err error
|
||||
master.privateKey, err = sm9.NewEncryptMasterPrivateKey(d.Bytes())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
master.MasterPublicKey = p
|
||||
return nil
|
||||
}
|
||||
|
||||
// pair generate the basepoint once
|
||||
func (pub *EncryptMasterPublicKey) pair() *bn256.GT {
|
||||
pub.pairOnce.Do(func() {
|
||||
pub.basePoint = bn256.Pair(pub.MasterPublicKey, bn256.Gen2)
|
||||
})
|
||||
return pub.basePoint
|
||||
// Equal compares the receiver EncryptMasterPublicKey with another EncryptMasterPublicKey
|
||||
// and returns true if they are equal, otherwise it returns false.
|
||||
func (pub *EncryptMasterPublicKey) Equal(x *EncryptMasterPublicKey) bool {
|
||||
return pub.publicKey.Equal(x.publicKey)
|
||||
}
|
||||
|
||||
func (pub *EncryptMasterPublicKey) generatorTable() *[32 * 2]bn256.GTFieldTable {
|
||||
pub.tableGenOnce.Do(func() {
|
||||
pub.table = bn256.GenerateGTFieldTable(pub.pair())
|
||||
})
|
||||
return pub.table
|
||||
}
|
||||
|
||||
// ScalarBaseMult compute basepoint^r with precomputed table.
|
||||
// The base point = pair(<master public key>, Gen2)
|
||||
func (pub *EncryptMasterPublicKey) ScalarBaseMult(scalar []byte) (*bn256.GT, error) {
|
||||
tables := pub.generatorTable()
|
||||
return bn256.ScalarBaseMultGT(tables, scalar)
|
||||
}
|
||||
|
||||
// GenerateUserPublicKey generate user encrypt public key
|
||||
func (pub *EncryptMasterPublicKey) GenerateUserPublicKey(uid []byte, hid byte) *bn256.G1 {
|
||||
var buffer []byte
|
||||
buffer = append(append(buffer, uid...), hid)
|
||||
h1 := hashH1(buffer)
|
||||
p, err := new(bn256.G1).ScalarBaseMult(h1.Bytes(orderNat))
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
p.Add(p, pub.MasterPublicKey)
|
||||
return p
|
||||
// Bytes returns the byte representation of the EncryptMasterPublicKey.
|
||||
// It delegates the call to the Bytes method of the underlying publicKey.
|
||||
func (pub *EncryptMasterPublicKey) Bytes() []byte {
|
||||
return pub.publicKey.Bytes()
|
||||
}
|
||||
|
||||
// MarshalASN1 marshal encrypt master public key to asn.1 format data according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
func (pub *EncryptMasterPublicKey) MarshalASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(pub.MasterPublicKey.MarshalUncompressed())
|
||||
b.AddASN1BitString(pub.publicKey.MasterPublicKey.MarshalUncompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -486,18 +348,16 @@ func (pub *EncryptMasterPublicKey) MarshalASN1() ([]byte, error) {
|
||||
// SM9 cryptographic algorithm application specification, the curve point is in compressed form.
|
||||
func (pub *EncryptMasterPublicKey) MarshalCompressedASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(pub.MasterPublicKey.MarshalCompressed())
|
||||
b.AddASN1BitString(pub.publicKey.MasterPublicKey.MarshalCompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to encrypt master public key
|
||||
func (pub *EncryptMasterPublicKey) UnmarshalRaw(bytes []byte) error {
|
||||
g, err := unmarshalG1(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
if pub.publicKey == nil {
|
||||
pub.publicKey = new(sm9.EncryptMasterPublicKey)
|
||||
}
|
||||
pub.MasterPublicKey = g
|
||||
return nil
|
||||
return pub.publicKey.UnmarshalRaw(bytes)
|
||||
}
|
||||
|
||||
// ParseFromPEM just for GMSSL, there are no Algorithm pkix.AlgorithmIdentifier
|
||||
@ -529,21 +389,19 @@ func (pub *EncryptMasterPublicKey) UnmarshalASN1(der []byte) error {
|
||||
|
||||
// MasterPublic returns the master public key corresponding to priv.
|
||||
func (priv *EncryptPrivateKey) MasterPublic() *EncryptMasterPublicKey {
|
||||
return priv.EncryptMasterPublicKey
|
||||
return &EncryptMasterPublicKey{priv.privateKey.MasterPublic()}
|
||||
}
|
||||
|
||||
// SetMasterPublicKey bind the encrypt master public key to it.
|
||||
func (priv *EncryptPrivateKey) SetMasterPublicKey(pub *EncryptMasterPublicKey) {
|
||||
if priv.EncryptMasterPublicKey == nil || priv.EncryptMasterPublicKey.MasterPublicKey == nil {
|
||||
priv.EncryptMasterPublicKey = pub
|
||||
}
|
||||
priv.privateKey.SetMasterPublicKey(pub.publicKey)
|
||||
}
|
||||
|
||||
// MarshalASN1 marshal encrypt user private key to asn.1 format data according
|
||||
// SM9 cryptographic algorithm application specification
|
||||
func (priv *EncryptPrivateKey) MarshalASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(priv.PrivateKey.MarshalUncompressed())
|
||||
b.AddASN1BitString(priv.privateKey.PrivateKey.MarshalUncompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
@ -551,19 +409,17 @@ func (priv *EncryptPrivateKey) MarshalASN1() ([]byte, error) {
|
||||
// SM9 cryptographic algorithm application specification, the curve point is in compressed form.
|
||||
func (priv *EncryptPrivateKey) MarshalCompressedASN1() ([]byte, error) {
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BitString(priv.PrivateKey.MarshalCompressed())
|
||||
b.AddASN1BitString(priv.privateKey.PrivateKey.MarshalCompressed())
|
||||
return b.Bytes()
|
||||
}
|
||||
|
||||
// UnmarshalRaw unmarsal raw bytes data to encrypt user private key
|
||||
// Note, priv's EncryptMasterPublicKey should be handled separately.
|
||||
func (priv *EncryptPrivateKey) UnmarshalRaw(bytes []byte) error {
|
||||
g, err := unmarshalG2(bytes)
|
||||
if err != nil {
|
||||
return err
|
||||
if priv.privateKey == nil {
|
||||
priv.privateKey = new(sm9.EncryptPrivateKey)
|
||||
}
|
||||
priv.PrivateKey = g
|
||||
return nil
|
||||
return priv.privateKey.UnmarshalRaw(bytes)
|
||||
}
|
||||
|
||||
// UnmarshalASN1 unmarsal der data to encrypt user private key
|
||||
@ -599,3 +455,15 @@ func (priv *EncryptPrivateKey) UnmarshalASN1(der []byte) error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Equal compares the receiver EncryptPrivateKey with another EncryptPrivateKey x
|
||||
// and returns true if they are equal, otherwise false.
|
||||
func (priv *EncryptPrivateKey) Equal(x *EncryptPrivateKey) bool {
|
||||
return priv.privateKey.Equal(x.privateKey)
|
||||
}
|
||||
|
||||
// Bytes returns the byte representation of the EncryptPrivateKey.
|
||||
// It delegates the call to the Bytes method of the underlying privateKey.
|
||||
func (priv *EncryptPrivateKey) Bytes() []byte {
|
||||
return priv.privateKey.Bytes()
|
||||
}
|
||||
|
@ -24,8 +24,8 @@ func TestSignMasterPrivateKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if masterKey.D.Cmp(masterKey2.D) != 0 {
|
||||
t.Errorf("expected %v, got %v", hex.EncodeToString(masterKey.D.Bytes()), hex.EncodeToString(masterKey2.D.Bytes()))
|
||||
if !masterKey.Equal(masterKey2) {
|
||||
t.Errorf("expected %v, got %v", hex.EncodeToString(masterKey.Bytes()), hex.EncodeToString(masterKey2.Bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -43,7 +43,7 @@ func TestSignMasterPublicKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !masterKey.MasterPublicKey.Equal(pub2.MasterPublicKey) {
|
||||
if !masterKey.Public().Equal(pub2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -62,7 +62,7 @@ func TestSignMasterPublicKeyMarshalCompressedASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !masterKey.MasterPublicKey.Equal(pub2.MasterPublicKey) {
|
||||
if !masterKey.Public().Equal(pub2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -87,7 +87,7 @@ func TestSignUserPrivateKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !userKey.PrivateKey.Equal(userKey2.PrivateKey) {
|
||||
if !userKey.Equal(userKey2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -112,7 +112,7 @@ func TestSignUserPrivateKeyMarshalCompressedASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !userKey.PrivateKey.Equal(userKey2.PrivateKey) {
|
||||
if !userKey.Equal(userKey2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -131,8 +131,8 @@ func TestEncryptMasterPrivateKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if masterKey.D.Cmp(masterKey2.D) != 0 {
|
||||
t.Errorf("expected %v, got %v", hex.EncodeToString(masterKey.D.Bytes()), hex.EncodeToString(masterKey2.D.Bytes()))
|
||||
if !masterKey.Equal(masterKey2) {
|
||||
t.Errorf("expected %v, got %v", hex.EncodeToString(masterKey.Bytes()), hex.EncodeToString(masterKey2.Bytes()))
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ func TestEncryptMasterPublicKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !masterKey.MasterPublicKey.Equal(pub2.MasterPublicKey) {
|
||||
if !masterKey.Public().Equal(pub2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -169,7 +169,7 @@ func TestEncryptMasterPublicKeyMarshalCompressedASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !masterKey.MasterPublicKey.Equal(pub2.MasterPublicKey) {
|
||||
if !masterKey.Public().Equal(pub2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -194,7 +194,7 @@ func TestEncryptUserPrivateKeyMarshalASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !userKey.PrivateKey.Equal(userKey2.PrivateKey) {
|
||||
if !userKey.Equal(userKey2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -219,7 +219,7 @@ func TestEncryptUserPrivateKeyMarshalCompressedASN1(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !userKey.PrivateKey.Equal(userKey2.PrivateKey) {
|
||||
if !userKey.Equal(userKey2) {
|
||||
t.Errorf("not same")
|
||||
}
|
||||
}
|
||||
@ -271,7 +271,7 @@ func TestParseSM9SignMasterPublicKey(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if key.MasterPublicKey == nil {
|
||||
if key == nil {
|
||||
t.Errorf("not expected nil")
|
||||
}
|
||||
|
||||
@ -305,7 +305,7 @@ func TestParseSM9EncryptMasterPublicKey(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if key.MasterPublicKey == nil {
|
||||
if key == nil {
|
||||
t.Errorf("not expected nil")
|
||||
}
|
||||
|
||||
@ -313,7 +313,7 @@ func TestParseSM9EncryptMasterPublicKey(t *testing.T) {
|
||||
var b cryptobyte.Builder
|
||||
|
||||
b.AddASN1(cryptobyte_asn1.SEQUENCE, func(b *cryptobyte.Builder) {
|
||||
b.AddASN1BitString(key.MasterPublicKey.MarshalUncompressed())
|
||||
b.AddASN1BitString(key.Bytes())
|
||||
})
|
||||
data, err := b.Bytes()
|
||||
if err != nil {
|
||||
|
764
sm9/sm9_test.go
764
sm9/sm9_test.go
@ -1,108 +1,12 @@
|
||||
package sm9
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/emmansun/gmsm/internal/bigmod"
|
||||
"github.com/emmansun/gmsm/internal/subtle"
|
||||
"github.com/emmansun/gmsm/sm3"
|
||||
"github.com/emmansun/gmsm/sm9/bn256"
|
||||
"golang.org/x/crypto/cryptobyte"
|
||||
)
|
||||
|
||||
func bigFromHex(s string) *big.Int {
|
||||
b, ok := new(big.Int).SetString(s, 16)
|
||||
if !ok {
|
||||
panic("sm9/elliptic: internal error: invalid encoding")
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func TestHashH1(t *testing.T) {
|
||||
expected := "2acc468c3926b0bdb2767e99ff26e084de9ced8dbc7d5fbf418027b667862fab"
|
||||
h := hashH1([]byte{0x41, 0x6c, 0x69, 0x63, 0x65, 0x01})
|
||||
if hex.EncodeToString(h.Bytes(orderNat)) != expected {
|
||||
t.Errorf("got %v, expected %v", h.Bytes(orderNat), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHashH2(t *testing.T) {
|
||||
expected := "823c4b21e4bd2dfe1ed92c606653e996668563152fc33f55d7bfbb9bd9705adb"
|
||||
zStr := "4368696E65736520494253207374616E6461726481377B8FDBC2839B4FA2D0E0F8AA6853BBBE9E9C4099608F8612C6078ACD7563815AEBA217AD502DA0F48704CC73CABB3C06209BD87142E14CBD99E8BCA1680F30DADC5CD9E207AEE32209F6C3CA3EC0D800A1A42D33C73153DED47C70A39D2E8EAF5D179A1836B359A9D1D9BFC19F2EFCDB829328620962BD3FDF15F2567F58A543D25609AE943920679194ED30328BB33FD15660BDE485C6B79A7B32B013983F012DB04BA59FE88DB889321CC2373D4C0C35E84F7AB1FF33679BCA575D67654F8624EB435B838CCA77B2D0347E65D5E46964412A096F4150D8C5EDE5440DDF0656FCB663D24731E80292188A2471B8B68AA993899268499D23C89755A1A89744643CEAD40F0965F28E1CD2895C3D118E4F65C9A0E3E741B6DD52C0EE2D25F5898D60848026B7EFB8FCC1B2442ECF0795F8A81CEE99A6248F294C82C90D26BD6A814AAF475F128AEF43A128E37F80154AE6CB92CAD7D1501BAE30F750B3A9BD1F96B08E97997363911314705BFB9A9DBB97F75553EC90FBB2DDAE53C8F68E42"
|
||||
z, err := hex.DecodeString(zStr)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := hashH2(z)
|
||||
if hex.EncodeToString(h.Bytes(orderNat)) != expected {
|
||||
t.Errorf("got %v, expected %v", h.Bytes(orderNat), expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSign(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
hid := byte(0x01)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h, s, err := Sign(rand.Reader, userKey, hashed)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !Verify(masterKey.Public(), uid, hid, hashed, h, s) {
|
||||
t.Errorf("Verify failed")
|
||||
}
|
||||
sNeg := new(bn256.G1).Neg(s)
|
||||
if Verify(masterKey.Public(), uid, hid, hashed, h, sNeg) {
|
||||
t.Errorf("Verify with s=-s succeeded")
|
||||
}
|
||||
hashed[0] ^= 0xff
|
||||
if Verify(masterKey.Public(), uid, hid, hashed, h, s) {
|
||||
t.Errorf("Verify always works!")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegativeInputs(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
hid := byte(0x01)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
h := new(big.Int).SetInt64(1)
|
||||
h.Lsh(h, 550 /* larger than any supported curve */)
|
||||
h.Neg(h)
|
||||
if Verify(masterKey.Public(), uid, hid, hashed, h, bn256.Gen1) {
|
||||
t.Errorf("bogus signature accepted")
|
||||
}
|
||||
}
|
||||
|
||||
func TestZeroSignature(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
hid := byte(0x01)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if Verify(masterKey.Public(), uid, hid, hashed, big.NewInt(0), bn256.Gen1) {
|
||||
t.Error("Verify with h=0 succeeded")
|
||||
}
|
||||
if Verify(masterKey.Public(), uid, hid, hashed, bn256.Order, bn256.Gen1) {
|
||||
t.Error("Verify with h=order succeeded")
|
||||
}
|
||||
}
|
||||
|
||||
func TestSignASN1(t *testing.T) {
|
||||
masterKey, err := GenerateSignMasterKey(rand.Reader)
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
@ -149,266 +53,6 @@ func TestParseInvalidASN1(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func signMasterPrivateKeyFromHex(s string) (*SignMasterPrivateKey, error) {
|
||||
kb, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(new(big.Int).SetBytes(kb))
|
||||
kb, _ = b.Bytes()
|
||||
testkey := new(SignMasterPrivateKey)
|
||||
err = testkey.UnmarshalASN1(kb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return testkey, nil
|
||||
}
|
||||
|
||||
// SM9 Appendix A
|
||||
func TestSignSM9Sample(t *testing.T) {
|
||||
expectedH := bigFromHex("823c4b21e4bd2dfe1ed92c606653e996668563152fc33f55d7bfbb9bd9705adb")
|
||||
expectedHNat, err := bigmod.NewNat().SetBytes(expectedH.Bytes(), orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
expectedS := "0473bf96923ce58b6ad0e13e9643a406d8eb98417c50ef1b29cef9adb48b6d598c856712f1c2e0968ab7769f42a99586aed139d5b8b3e15891827cc2aced9baa05"
|
||||
hash := []byte("Chinese IBS standard")
|
||||
hid := byte(0x01)
|
||||
uid := []byte("Alice")
|
||||
r := bigFromHex("033c8616b06704813203dfd00965022ed15975c662337aed648835dc4b1cbe")
|
||||
rNat, err := bigmod.NewNat().SetBytes(r.Bytes(), orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
masterKey, err := signMasterPrivateKeyFromHex("0130E78459D78545CB54C587E02CF480CE0B66340F319F348A1D5B1F2DC5F4")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
w, err := userKey.SignMasterPublicKey.ScalarBaseMult(bn256.NormalizeScalar(r.Bytes()))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
var buffer []byte
|
||||
buffer = append(buffer, hash...)
|
||||
buffer = append(buffer, w.Marshal()...)
|
||||
|
||||
h := hashH2(buffer)
|
||||
if h.Equal(expectedHNat) == 0 {
|
||||
t.Fatal("not same h")
|
||||
}
|
||||
|
||||
rNat.Sub(h, orderNat)
|
||||
|
||||
s, err := new(bn256.G1).ScalarMult(userKey.PrivateKey, rNat.Bytes(orderNat))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(s.MarshalUncompressed()) != expectedS {
|
||||
t.Fatal("not same S")
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix B
|
||||
func TestKeyExchangeSample(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
expectedPube := "9174542668e8f14ab273c0945c3690c66e5dd09678b86f734c4350567ed0628354e598c6bf749a3dacc9fffedd9db6866c50457cfc7aa2a4ad65c3168ff74210"
|
||||
expectedKey := "c5c13a8f59a97cdeae64f16a2272a9e7"
|
||||
expectedSignatureB := "3bb4bcee8139c960b4d6566db1e0d5f0b2767680e5e1bf934103e6c66e40ffee"
|
||||
expectedSignatureA := "195d1b7256ba7e0e67c71202a25f8c94ff8241702c2f55d613ae1c6b98215172"
|
||||
|
||||
masterKey, err := encryptMasterPrivateKeyFromHex("02E65B0762D042F51F0D23542B13ED8CFA2E9A0E7206361E013A283905E31F")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(masterKey.MasterPublicKey.Marshal()) != expectedPube {
|
||||
t.Errorf("not expected master public key")
|
||||
}
|
||||
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := NewKeyExchange(userKey, userA, userB, 16, true)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := NewKeyExchange(userKey, userB, userA, 16, true)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
k, err := bigmod.NewNat().SetBytes(bigFromHex("5879DD1D51E175946F23B1B41E93BA31C584AE59A426EC1046A4D03B06C8").Bytes(), orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initKeyExchange(initiator, hid, k)
|
||||
|
||||
if hex.EncodeToString(initiator.secret.Marshal()) != "7cba5b19069ee66aa79d490413d11846b9ba76dd22567f809cf23b6d964bb265a9760c99cb6f706343fed05637085864958d6c90902aba7d405fbedf7b781599" {
|
||||
t.Fatal("not same")
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
k, err = bigmod.NewNat().SetBytes(bigFromHex("018B98C44BEF9F8537FB7D071B2C928B3BC65BD3D69E1EEE213564905634FE").Bytes(), orderNat)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
rB, sigB, err := respondKeyExchange(responder, hid, k, initiator.secret)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(sigB) != expectedSignatureB {
|
||||
t.Errorf("not expected signature B")
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hex.EncodeToString(key1) != expectedKey {
|
||||
t.Errorf("not expected key %v\n", hex.EncodeToString(key1))
|
||||
}
|
||||
if hex.EncodeToString(sigA) != expectedSignatureA {
|
||||
t.Errorf("not expected signature A")
|
||||
}
|
||||
// B8
|
||||
key2, err := responder.ConfirmInitiator(sigA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hex.EncodeToString(key2) != expectedKey {
|
||||
t.Errorf("not expected key %v\n", hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyExchange(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := NewKeyExchange(userKey, userA, userB, 16, true)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := NewKeyExchange(userKey, userB, userA, 16, true)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
rA, err := initiator.InitKeyExchange(rand.Reader, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
rB, sigB, err := responder.RepondKeyExchange(rand.Reader, hid, rA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B8
|
||||
key2, err := responder.ConfirmInitiator(sigA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("got different key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyExchangeWithoutSignature(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := NewKeyExchange(userKey, userA, userB, 16, false)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := NewKeyExchange(userKey, userB, userA, 16, false)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
rA, err := initiator.InitKeyExchange(rand.Reader, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
rB, sigB, err := responder.RepondKeyExchange(rand.Reader, hid, rA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sigB) != 0 {
|
||||
t.Errorf("should no signature")
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sigA) != 0 {
|
||||
t.Errorf("should no signature")
|
||||
}
|
||||
|
||||
key2, err := responder.ConfirmInitiator(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("got different key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWrapKey(t *testing.T) {
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
hid := byte(0x01)
|
||||
@ -420,18 +64,18 @@ func TestWrapKey(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
key, cipher, err := WrapKey(rand.Reader, masterKey.Public(), uid, hid, 16)
|
||||
key, cipher, err := masterKey.Public().WrapKey(rand.Reader, uid, hid, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key2, err := UnwrapKey(userKey, uid, cipher, 16)
|
||||
key2, err := userKey.UnwrapKey(uid, cipher, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key) != hex.EncodeToString(key2) {
|
||||
t.Errorf("expected %v, got %v\n", hex.EncodeToString(key), hex.EncodeToString(key2))
|
||||
if !bytes.Equal(key, key2) {
|
||||
t.Errorf("expected %x, got %x", key, key2)
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,260 +105,8 @@ func TestWrapKeyASN1(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("expected %v, got %v\n", hex.EncodeToString(key1), hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalSM9KeyPackage(t *testing.T) {
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
hid := byte(0x01)
|
||||
uid := []byte("emmansun")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p, err := masterKey.Public().WrapKeyASN1(rand.Reader, uid, hid, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key, cipher, err := UnmarshalSM9KeyPackage(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key2, err := UnwrapKey(userKey, uid, cipher, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key) != hex.EncodeToString(key2) {
|
||||
t.Errorf("expected %v, got %v\n", hex.EncodeToString(key), hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
||||
|
||||
func encryptMasterPrivateKeyFromHex(s string) (*EncryptMasterPrivateKey, error) {
|
||||
kb, err := hex.DecodeString(s)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var b cryptobyte.Builder
|
||||
b.AddASN1BigInt(new(big.Int).SetBytes(kb))
|
||||
kb, _ = b.Bytes()
|
||||
testkey := new(EncryptMasterPrivateKey)
|
||||
err = testkey.UnmarshalASN1(kb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return testkey, nil
|
||||
}
|
||||
|
||||
// SM9 Appendix C
|
||||
func TestWrapKeySM9Sample(t *testing.T) {
|
||||
expectedMasterPublicKey := "787ed7b8a51f3ab84e0a66003f32da5c720b17eca7137d39abc66e3c80a892ff769de61791e5adc4b9ff85a31354900b202871279a8c49dc3f220f644c57a7b1"
|
||||
expectedUserPrivateKey := "94736acd2c8c8796cc4785e938301a139a059d3537b6414140b2d31eecf41683115bae85f5d8bc6c3dbd9e5342979acccf3c2f4f28420b1cb4f8c0b59a19b1587aa5e47570da7600cd760a0cf7beaf71c447f3844753fe74fa7ba92ca7d3b55f27538a62e7f7bfb51dce08704796d94c9d56734f119ea44732b50e31cdeb75c1"
|
||||
expectedUserPublicKey := "709d165808b0a43e2574e203fa885abcbab16a240c4c1916552e7c43d09763b8693269a6be2456f43333758274786b6051ff87b7f198da4ba1a2c6e336f51fcc"
|
||||
expectedCipher := "1edee2c3f465914491de44cefb2cb434ab02c308d9dc5e2067b4fed5aaac8a0f1c9b4c435eca35ab83bb734174c0f78fde81a53374aff3b3602bbc5e37be9a4c"
|
||||
expectedKey := "4ff5cf86d2ad40c8f4bac98d76abdbde0c0e2f0a829d3f911ef5b2bce0695480"
|
||||
|
||||
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("74015F8489C01EF4270456F9E6475BFB602BDE7F33FD482AB4E3684A6722")
|
||||
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 := sm3.Kdf(buffer, 32)
|
||||
|
||||
if hex.EncodeToString(key) != expectedKey {
|
||||
t.Errorf("expected %v, got %v\n", expectedKey, hex.EncodeToString(key))
|
||||
}
|
||||
|
||||
key2, err := UnwrapKey(userKey, uid, cipher, 32)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if hex.EncodeToString(key2) != expectedKey {
|
||||
t.Errorf("expected %v, got %v\n", expectedKey, hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
||||
|
||||
// SM9 Appendix D
|
||||
func TestEncryptSM9Sample(t *testing.T) {
|
||||
plaintext := []byte("Chinese IBE standard")
|
||||
expectedMasterPublicKey := "787ed7b8a51f3ab84e0a66003f32da5c720b17eca7137d39abc66e3c80a892ff769de61791e5adc4b9ff85a31354900b202871279a8c49dc3f220f644c57a7b1"
|
||||
expectedUserPrivateKey := "94736acd2c8c8796cc4785e938301a139a059d3537b6414140b2d31eecf41683115bae85f5d8bc6c3dbd9e5342979acccf3c2f4f28420b1cb4f8c0b59a19b1587aa5e47570da7600cd760a0cf7beaf71c447f3844753fe74fa7ba92ca7d3b55f27538a62e7f7bfb51dce08704796d94c9d56734f119ea44732b50e31cdeb75c1"
|
||||
expectedUserPublicKey := "709d165808b0a43e2574e203fa885abcbab16a240c4c1916552e7c43d09763b8693269a6be2456f43333758274786b6051ff87b7f198da4ba1a2c6e336f51fcc"
|
||||
expectedCipher := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0"
|
||||
expectedKey := "58373260f067ec48667c21c144f8bc33cd3049788651ffd5f738003e51df31174d0e4e402fd87f4581b612f74259db574f67ece6"
|
||||
expectedCiphertext := "2445471164490618e1ee20528ff1d545b0f14c8bcaa44544f03dab5dac07d8ff42ffca97d57cddc05ea405f2e586feb3a6930715532b8000759f13059ed59ac0ba672387bcd6de5016a158a52bb2e7fc429197bcab70b25afee37a2b9db9f3671b5f5b0e951489682f3e64e1378cdd5da9513b1c"
|
||||
|
||||
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 := sm3.Kdf(buffer, len(plaintext)+32)
|
||||
|
||||
if hex.EncodeToString(key) != expectedKey {
|
||||
t.Errorf("not expected key")
|
||||
}
|
||||
subtle.XORBytes(key, key[:len(plaintext)], plaintext)
|
||||
|
||||
hash := sm3.New()
|
||||
hash.Write(key)
|
||||
c3 := hash.Sum(nil)
|
||||
|
||||
ciphertext := append(cipher.Marshal(), c3...)
|
||||
ciphertext = append(ciphertext, key[:len(plaintext)]...)
|
||||
if hex.EncodeToString(ciphertext) != expectedCiphertext {
|
||||
t.Errorf("expected %v, got %v\n", expectedCiphertext, hex.EncodeToString(ciphertext))
|
||||
}
|
||||
}
|
||||
|
||||
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 := sm3.Kdf(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))
|
||||
if !bytes.Equal(key1, key2) {
|
||||
t.Errorf("expected %x, got %x", key1, key2)
|
||||
}
|
||||
}
|
||||
|
||||
@ -817,6 +209,148 @@ func TestEncryptDecryptASN1(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshalSM9KeyPackage(t *testing.T) {
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
hid := byte(0x01)
|
||||
uid := []byte("emmansun")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
userKey, err := masterKey.GenerateUserKey(uid, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
p, err := masterKey.Public().WrapKeyASN1(rand.Reader, uid, hid, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key, cipher, err := UnmarshalSM9KeyPackage(p)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
key2, err := UnwrapKey(userKey, uid, cipher, 16)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key) != hex.EncodeToString(key2) {
|
||||
t.Errorf("expected %v, got %v\n", hex.EncodeToString(key), hex.EncodeToString(key2))
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyExchange(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := userKey.NewKeyExchange(userA, userB, 16, true)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := userKey.NewKeyExchange(userB, userA, 16, true)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
rA, err := initiator.InitKeyExchange(rand.Reader, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
rB, sigB, err := responder.RespondKeyExchange(rand.Reader, hid, rA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B8
|
||||
key2, err := responder.ConfirmInitiator(sigA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("got different key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestKeyExchangeWithoutSignature(t *testing.T) {
|
||||
hid := byte(0x02)
|
||||
userA := []byte("Alice")
|
||||
userB := []byte("Bob")
|
||||
masterKey, err := GenerateEncryptMasterKey(rand.Reader)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
userKey, err := masterKey.GenerateUserKey(userA, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
initiator := userKey.NewKeyExchange(userA, userB, 16, false)
|
||||
|
||||
userKey, err = masterKey.GenerateUserKey(userB, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
responder := userKey.NewKeyExchange(userB, userA, 16, false)
|
||||
defer func() {
|
||||
initiator.Destroy()
|
||||
responder.Destroy()
|
||||
}()
|
||||
// A1-A4
|
||||
rA, err := initiator.InitKeyExchange(rand.Reader, hid)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// B1 - B7
|
||||
rB, sigB, err := responder.RespondKeyExchange(rand.Reader, hid, rA)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sigB) != 0 {
|
||||
t.Errorf("should no signature")
|
||||
}
|
||||
|
||||
// A5 -A8
|
||||
key1, sigA, err := initiator.ConfirmResponder(rB, sigB)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if len(sigA) != 0 {
|
||||
t.Errorf("should no signature")
|
||||
}
|
||||
|
||||
key2, err := responder.ConfirmInitiator(nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if hex.EncodeToString(key1) != hex.EncodeToString(key2) {
|
||||
t.Errorf("got different key")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkSign(b *testing.B) {
|
||||
hashed := []byte("Chinese IBS standard")
|
||||
uid := []byte("emmansun")
|
||||
|
@ -219,8 +219,7 @@ func TestMarshalPKCS8SM9SignPrivateKey(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("not expected key")
|
||||
}
|
||||
if !privateKey.PrivateKey.Equal(privateKey2.PrivateKey) ||
|
||||
!privateKey.MasterPublicKey.Equal(privateKey2.MasterPublicKey) {
|
||||
if !privateKey.Equal(privateKey2) {
|
||||
t.Fatalf("not same key")
|
||||
}
|
||||
}
|
||||
@ -246,8 +245,7 @@ func TestMarshalPKCS8SM9EncPrivateKey(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("not expected key")
|
||||
}
|
||||
if !privateKey.PrivateKey.Equal(privateKey2.PrivateKey) ||
|
||||
!privateKey.MasterPublicKey.Equal(privateKey2.MasterPublicKey) {
|
||||
if !privateKey.Equal(privateKey2) {
|
||||
t.Fatalf("not same key")
|
||||
}
|
||||
}
|
||||
@ -269,8 +267,8 @@ func TestMarshalPKCS8SM9SignMasterPrivateKey(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("not expected key")
|
||||
}
|
||||
masterKey2.MasterPublicKey.Marshal()
|
||||
if !(masterKey.D.Cmp(masterKey2.D) == 0 && masterKey.MasterPublicKey.Equal(masterKey2.MasterPublicKey)) {
|
||||
|
||||
if !masterKey.Equal(masterKey2) {
|
||||
t.Fatalf("not same key")
|
||||
}
|
||||
}
|
||||
@ -292,8 +290,7 @@ func TestMarshalPKCS8SM9EncMasterPrivateKey(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatalf("not expected key")
|
||||
}
|
||||
masterKey2.MasterPublicKey.Marshal()
|
||||
if !(masterKey.D.Cmp(masterKey2.D) == 0 && masterKey.MasterPublicKey.Equal(masterKey2.MasterPublicKey)) {
|
||||
if !masterKey.Equal(masterKey2) {
|
||||
t.Fatalf("not same key")
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user