mirror of
https://github.com/emmansun/gmsm.git
synced 2025-04-26 04:06:18 +08:00
sm2/9: key exchange error message and comment
This commit is contained in:
parent
fb53e7eb71
commit
3f550e2f24
@ -2,7 +2,7 @@ package sm2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
goSubtle "crypto/subtle"
|
"crypto/subtle"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
"math/big"
|
"math/big"
|
||||||
@ -109,7 +109,7 @@ func initKeyExchange(ke *KeyExchange, r *big.Int) {
|
|||||||
ke.r = r
|
ke.r = r
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitKeyExchange generate random with responder uid, for initiator's step A1-A3
|
// InitKeyExchange is for initiator's step A1-A3, returns generated Ephemeral Public Key which will be passed to Reponder.
|
||||||
func (ke *KeyExchange) InitKeyExchange(rand io.Reader) (*ecdsa.PublicKey, error) {
|
func (ke *KeyExchange) InitKeyExchange(rand io.Reader) (*ecdsa.PublicKey, error) {
|
||||||
r, err := randFieldElement(ke.privateKey, rand)
|
r, err := randFieldElement(ke.privateKey, rand)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -162,27 +162,30 @@ func (ke *KeyExchange) generateSharedKey(isResponder bool) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func respondKeyExchange(ke *KeyExchange, r *big.Int) (*ecdsa.PublicKey, []byte, error) {
|
func respondKeyExchange(ke *KeyExchange, r *big.Int) (*ecdsa.PublicKey, []byte, error) {
|
||||||
|
// secret = RB = [r]G
|
||||||
ke.secret.X, ke.secret.Y = ke.privateKey.ScalarBaseMult(r.Bytes())
|
ke.secret.X, ke.secret.Y = ke.privateKey.ScalarBaseMult(r.Bytes())
|
||||||
ke.r = r
|
ke.r = r
|
||||||
// Calculate tB
|
// Calculate x2`
|
||||||
t := (&big.Int{}).And(ke.w2Minus1, ke.secret.X)
|
t := (&big.Int{}).And(ke.w2Minus1, ke.secret.X)
|
||||||
t.Add(ke.w2, t)
|
t.Add(ke.w2, t)
|
||||||
|
|
||||||
|
// Calculate tB
|
||||||
t.Mul(t, ke.r)
|
t.Mul(t, ke.r)
|
||||||
t.Add(t, ke.privateKey.D)
|
t.Add(t, ke.privateKey.D)
|
||||||
t.Mod(t, ke.privateKey.Params().N)
|
t.Mod(t, ke.privateKey.Params().N)
|
||||||
|
|
||||||
/* x1 = 2^w + (x & (2^w – 1)) */
|
// x1` = 2^w + (x & (2^w – 1))
|
||||||
x1 := (&big.Int{}).And(ke.w2Minus1, ke.peerSecret.X)
|
x1 := (&big.Int{}).And(ke.w2Minus1, ke.peerSecret.X)
|
||||||
x1.Add(ke.w2, x1)
|
x1.Add(ke.w2, x1)
|
||||||
|
|
||||||
/* Point(x3, y3) = peerPub + [x1](peerSecret) */
|
// Point(x3, y3) = peerPub + [x1](peerSecret)
|
||||||
x3, y3 := ke.privateKey.ScalarMult(ke.peerSecret.X, ke.peerSecret.Y, x1.Bytes())
|
x3, y3 := ke.privateKey.ScalarMult(ke.peerSecret.X, ke.peerSecret.Y, x1.Bytes())
|
||||||
x3, y3 = ke.privateKey.Add(ke.peerPub.X, ke.peerPub.Y, x3, y3)
|
x3, y3 = ke.privateKey.Add(ke.peerPub.X, ke.peerPub.Y, x3, y3)
|
||||||
|
|
||||||
/* V = [h*tB](Point(x3, y3)) */
|
// V = [h*tB](Point(x3, y3))
|
||||||
ke.v.X, ke.v.Y = ke.privateKey.ScalarMult(x3, y3, t.Bytes())
|
ke.v.X, ke.v.Y = ke.privateKey.ScalarMult(x3, y3, t.Bytes())
|
||||||
if ke.v.X.Sign() == 0 && ke.v.Y.Sign() == 0 {
|
if ke.v.X.Sign() == 0 && ke.v.Y.Sign() == 0 {
|
||||||
return nil, nil, errors.New("sm2: key exchange fail")
|
return nil, nil, errors.New("sm2: key exchange failed, V is infinity point")
|
||||||
}
|
}
|
||||||
|
|
||||||
ke.generateSharedKey(true)
|
ke.generateSharedKey(true)
|
||||||
@ -194,14 +197,16 @@ func respondKeyExchange(ke *KeyExchange, r *big.Int) (*ecdsa.PublicKey, []byte,
|
|||||||
return ke.secret, ke.sign(true, 0x02), nil
|
return ke.secret, ke.sign(true, 0x02), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RepondKeyExchange when responder receive rA, for responder's step B1-B8
|
// RepondKeyExchange is for responder's step B1-B8, returns generated Ephemeral Public Key and optional signature
|
||||||
// rA - Received Peer's Ephemeral Public Key
|
// depends on KeyExchange.genSignature value.
|
||||||
|
//
|
||||||
|
// It will check if there are peer's public key and validate the peer's Ephemeral Public Key.
|
||||||
func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, rA *ecdsa.PublicKey) (*ecdsa.PublicKey, []byte, error) {
|
func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, rA *ecdsa.PublicKey) (*ecdsa.PublicKey, []byte, error) {
|
||||||
if ke.peerPub == nil {
|
if ke.peerPub == nil {
|
||||||
return nil, nil, errors.New("sm2: peer public not set, you probable need call KeyExchange.SetPeerParameters")
|
return nil, nil, errors.New("sm2: no peer public key given")
|
||||||
}
|
}
|
||||||
if !ke.privateKey.IsOnCurve(rA.X, rA.Y) {
|
if !ke.privateKey.IsOnCurve(rA.X, rA.Y) {
|
||||||
return nil, nil, errors.New("sm2: received invalid random from initiator")
|
return nil, nil, errors.New("sm2: invalid initiator's ephemeral public key")
|
||||||
}
|
}
|
||||||
ke.peerSecret = rA
|
ke.peerSecret = rA
|
||||||
r, err := randFieldElement(ke.privateKey, rand)
|
r, err := randFieldElement(ke.privateKey, rand)
|
||||||
@ -211,13 +216,18 @@ func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, rA *ecdsa.PublicKey) (*
|
|||||||
return respondKeyExchange(ke, r)
|
return respondKeyExchange(ke, r)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ConfirmResponder for initiator's step A4-A10
|
// ConfirmResponder for initiator's step A4-A10, returns optional signature.
|
||||||
|
//
|
||||||
|
// It will check if there are peer's public key and validate the peer's Ephemeral Public Key.
|
||||||
|
//
|
||||||
|
// If the peer's signature is not empty, then it will also validate the peer's
|
||||||
|
// signature and return generated signature regardless KeyExchange.genSignature value.
|
||||||
func (ke *KeyExchange) ConfirmResponder(rB *ecdsa.PublicKey, sB []byte) ([]byte, error) {
|
func (ke *KeyExchange) ConfirmResponder(rB *ecdsa.PublicKey, sB []byte) ([]byte, error) {
|
||||||
if ke.peerPub == nil {
|
if ke.peerPub == nil {
|
||||||
return nil, errors.New("sm2: peer public not set, you probable need call KeyExchange.SetPeerParameters")
|
return nil, errors.New("sm2: no peer public key given")
|
||||||
}
|
}
|
||||||
if !ke.privateKey.IsOnCurve(rB.X, rB.Y) {
|
if !ke.privateKey.IsOnCurve(rB.X, rB.Y) {
|
||||||
return nil, errors.New("sm2: received invalid random from responder")
|
return nil, errors.New("sm2: invalid responder's ephemeral public key")
|
||||||
}
|
}
|
||||||
ke.peerSecret = rB
|
ke.peerSecret = rB
|
||||||
// Calculate tA
|
// Calculate tA
|
||||||
@ -227,25 +237,25 @@ func (ke *KeyExchange) ConfirmResponder(rB *ecdsa.PublicKey, sB []byte) ([]byte,
|
|||||||
t.Add(t, ke.privateKey.D)
|
t.Add(t, ke.privateKey.D)
|
||||||
t.Mod(t, ke.privateKey.Params().N)
|
t.Mod(t, ke.privateKey.Params().N)
|
||||||
|
|
||||||
/* x2 = 2^w + (x & (2^w – 1)) */
|
// x2` = 2^w + (x & (2^w – 1))
|
||||||
x2 := (&big.Int{}).And(ke.w2Minus1, ke.peerSecret.X)
|
x2 := (&big.Int{}).And(ke.w2Minus1, ke.peerSecret.X)
|
||||||
x2.Add(ke.w2, x2)
|
x2.Add(ke.w2, x2)
|
||||||
|
|
||||||
/* Point(x3, y3) = peerPub + [x1](peerSecret) */
|
// Point(x3, y3) = peerPub + [x1](peerSecret)
|
||||||
x3, y3 := ke.privateKey.ScalarMult(ke.peerSecret.X, ke.peerSecret.Y, x2.Bytes())
|
x3, y3 := ke.privateKey.ScalarMult(ke.peerSecret.X, ke.peerSecret.Y, x2.Bytes())
|
||||||
x3, y3 = ke.privateKey.Add(ke.peerPub.X, ke.peerPub.Y, x3, y3)
|
x3, y3 = ke.privateKey.Add(ke.peerPub.X, ke.peerPub.Y, x3, y3)
|
||||||
|
|
||||||
/* V = [h*tA](Point(x3, y3)) */
|
// U = [h*tA](Point(x3, y3))
|
||||||
ke.v.X, ke.v.Y = ke.privateKey.ScalarMult(x3, y3, t.Bytes())
|
ke.v.X, ke.v.Y = ke.privateKey.ScalarMult(x3, y3, t.Bytes())
|
||||||
|
|
||||||
if ke.v.X.Sign() == 0 && ke.v.Y.Sign() == 0 {
|
if ke.v.X.Sign() == 0 && ke.v.Y.Sign() == 0 {
|
||||||
return nil, errors.New("sm2: key exchange fail")
|
return nil, errors.New("sm2: key exchange failed, U is infinity point")
|
||||||
}
|
}
|
||||||
ke.generateSharedKey(false)
|
ke.generateSharedKey(false)
|
||||||
if len(sB) > 0 {
|
if len(sB) > 0 {
|
||||||
buffer := ke.sign(false, 0x02)
|
buffer := ke.sign(false, 0x02)
|
||||||
if goSubtle.ConstantTimeCompare(buffer, sB) != 1 {
|
if subtle.ConstantTimeCompare(buffer, sB) != 1 {
|
||||||
return nil, errors.New("sm2: verify responder's signature fail")
|
return nil, errors.New("sm2: invalid responder's signature")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ke.sign(false, 0x03), nil
|
return ke.sign(false, 0x03), nil
|
||||||
@ -254,8 +264,8 @@ func (ke *KeyExchange) ConfirmResponder(rB *ecdsa.PublicKey, sB []byte) ([]byte,
|
|||||||
// ConfirmInitiator for responder's step B10
|
// ConfirmInitiator for responder's step B10
|
||||||
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
|
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
|
||||||
buffer := ke.sign(true, 0x03)
|
buffer := ke.sign(true, 0x03)
|
||||||
if goSubtle.ConstantTimeCompare(buffer, s1) != 1 {
|
if subtle.ConstantTimeCompare(buffer, s1) != 1 {
|
||||||
return errors.New("sm2: verify initiator's signature fail")
|
return errors.New("sm2: invalid initiator's signature")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -68,6 +68,13 @@ func TestSetPeerParameters(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call twice
|
||||||
|
err = initiator.SetPeerParameters(&priv2.PublicKey, uidB)
|
||||||
|
if err == nil {
|
||||||
|
t.Fatalf("expected error")
|
||||||
|
}
|
||||||
|
|
||||||
err = responder.SetPeerParameters(&priv1.PublicKey, uidA)
|
err = responder.SetPeerParameters(&priv1.PublicKey, uidA)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
|
@ -552,7 +552,7 @@ func (ke *KeyExchange) generateSharedKey(isResponder bool) {
|
|||||||
|
|
||||||
func respondKeyExchange(ke *KeyExchange, hid byte, r *big.Int, rA *bn256.G1) (*bn256.G1, []byte, error) {
|
func respondKeyExchange(ke *KeyExchange, hid byte, r *big.Int, rA *bn256.G1) (*bn256.G1, []byte, error) {
|
||||||
if !rA.IsOnCurve() {
|
if !rA.IsOnCurve() {
|
||||||
return nil, nil, errors.New("sm9: received invalid random from initiator")
|
return nil, nil, errors.New("sm9: invalid initiator's ephemeral public key")
|
||||||
}
|
}
|
||||||
ke.peerSecret = rA
|
ke.peerSecret = rA
|
||||||
pubA := ke.privateKey.GenerateUserPublicKey(ke.peerUID, hid)
|
pubA := ke.privateKey.GenerateUserPublicKey(ke.peerUID, hid)
|
||||||
@ -586,7 +586,7 @@ func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, hid byte, rA *bn256.G1)
|
|||||||
// ConfirmResponder for initiator's step A5-A7
|
// ConfirmResponder for initiator's step A5-A7
|
||||||
func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error) {
|
func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error) {
|
||||||
if !rB.IsOnCurve() {
|
if !rB.IsOnCurve() {
|
||||||
return nil, errors.New("sm9: received invalid random from responder")
|
return nil, errors.New("sm9: invalid responder's ephemeral public key")
|
||||||
}
|
}
|
||||||
// step 5
|
// step 5
|
||||||
ke.peerSecret = rB
|
ke.peerSecret = rB
|
||||||
@ -598,7 +598,7 @@ func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error)
|
|||||||
if len(sB) > 0 {
|
if len(sB) > 0 {
|
||||||
signature := ke.sign(false, 0x82)
|
signature := ke.sign(false, 0x82)
|
||||||
if subtle.ConstantTimeCompare(signature, sB) != 1 {
|
if subtle.ConstantTimeCompare(signature, sB) != 1 {
|
||||||
return nil, errors.New("sm9: verify responder's signature fail")
|
return nil, errors.New("sm9: invalid responder's signature")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ke.generateSharedKey(false)
|
ke.generateSharedKey(false)
|
||||||
@ -610,7 +610,7 @@ func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error)
|
|||||||
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
|
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
|
||||||
buffer := ke.sign(true, 0x83)
|
buffer := ke.sign(true, 0x83)
|
||||||
if subtle.ConstantTimeCompare(buffer, s1) != 1 {
|
if subtle.ConstantTimeCompare(buffer, s1) != 1 {
|
||||||
return errors.New("sm9: verify initiator's signature fail")
|
return errors.New("sm9: invalid initiator's signature")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user