sm2/9: key exchange error message and comment

This commit is contained in:
Sun Yimin 2022-08-17 11:17:18 +08:00 committed by GitHub
parent fb53e7eb71
commit 3f550e2f24
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 43 additions and 26 deletions

View File

@ -2,7 +2,7 @@ package sm2
import (
"crypto/ecdsa"
goSubtle "crypto/subtle"
"crypto/subtle"
"errors"
"io"
"math/big"
@ -109,7 +109,7 @@ func initKeyExchange(ke *KeyExchange, r *big.Int) {
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) {
r, err := randFieldElement(ke.privateKey, rand)
if err != nil {
@ -162,27 +162,30 @@ func (ke *KeyExchange) generateSharedKey(isResponder bool) {
}
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.r = r
// Calculate tB
// Calculate x2`
t := (&big.Int{}).And(ke.w2Minus1, ke.secret.X)
t.Add(ke.w2, t)
// Calculate tB
t.Mul(t, ke.r)
t.Add(t, ke.privateKey.D)
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.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.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())
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)
@ -194,14 +197,16 @@ func respondKeyExchange(ke *KeyExchange, r *big.Int) (*ecdsa.PublicKey, []byte,
return ke.secret, ke.sign(true, 0x02), nil
}
// RepondKeyExchange when responder receive rA, for responder's step B1-B8
// rA - Received Peer's Ephemeral Public Key
// RepondKeyExchange is for responder's step B1-B8, returns generated Ephemeral Public Key and optional signature
// 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) {
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) {
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
r, err := randFieldElement(ke.privateKey, rand)
@ -211,13 +216,18 @@ func (ke *KeyExchange) RepondKeyExchange(rand io.Reader, rA *ecdsa.PublicKey) (*
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) {
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) {
return nil, errors.New("sm2: received invalid random from responder")
return nil, errors.New("sm2: invalid responder's ephemeral public key")
}
ke.peerSecret = rB
// Calculate tA
@ -227,25 +237,25 @@ func (ke *KeyExchange) ConfirmResponder(rB *ecdsa.PublicKey, sB []byte) ([]byte,
t.Add(t, ke.privateKey.D)
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.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.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())
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)
if len(sB) > 0 {
buffer := ke.sign(false, 0x02)
if goSubtle.ConstantTimeCompare(buffer, sB) != 1 {
return nil, errors.New("sm2: verify responder's signature fail")
if subtle.ConstantTimeCompare(buffer, sB) != 1 {
return nil, errors.New("sm2: invalid responder's signature")
}
}
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
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
buffer := ke.sign(true, 0x03)
if goSubtle.ConstantTimeCompare(buffer, s1) != 1 {
return errors.New("sm2: verify initiator's signature fail")
if subtle.ConstantTimeCompare(buffer, s1) != 1 {
return errors.New("sm2: invalid initiator's signature")
}
return nil
}

View File

@ -68,6 +68,13 @@ func TestSetPeerParameters(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// call twice
err = initiator.SetPeerParameters(&priv2.PublicKey, uidB)
if err == nil {
t.Fatalf("expected error")
}
err = responder.SetPeerParameters(&priv1.PublicKey, uidA)
if err != nil {
t.Fatal(err)

View File

@ -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) {
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
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
func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error) {
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
ke.peerSecret = rB
@ -598,7 +598,7 @@ func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error)
if len(sB) > 0 {
signature := ke.sign(false, 0x82)
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)
@ -610,7 +610,7 @@ func (ke *KeyExchange) ConfirmResponder(rB *bn256.G1, sB []byte) ([]byte, error)
func (ke *KeyExchange) ConfirmInitiator(s1 []byte) error {
buffer := ke.sign(true, 0x83)
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
}