Files
xgcl/tpc/sm2/sm2m/gen_sign_key.go
T
2026-05-27 23:03:00 +08:00

117 lines
3.3 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package sm2m
import (
"errors"
"fmt"
"io"
"math/big"
"xdx.jelly/xgcl/gerrors"
"xdx.jelly/xgcl/gmath"
"xdx.jelly/xgcl/grand"
"xdx.jelly/xgcl/sm/sm2"
)
/*
服务端和用户端的秘钥生成
秘钥关系式: (1 + d)^(-1)= d1 * d2
签名(加密)秘钥双方生成流程
a0 客户端初始化context
a1 客户端(), 向服务端发送数据。
b1 服务端结收数据计算并发回数据()
a2 客户端接收数据并计算,输出签名
a3 客户端清理context
*/
// clientKey = d1
// clientTempPublicKey = [d1^(-1)]*G
func ClientGenSignKey_one(rnd any) (clientKey *sm2.PrivateKey, clientTempPublicKey *sm2.PublicKey, err error) {
if rnd == nil {
rnd = grand.Reader
}
switch rnd := rnd.(type) {
case io.Reader:
clientKey, err := sm2.GenerateKey(sm2.Curve(), rnd)
if err != nil {
return nil, nil, err
}
clientTempPublicKey := &clientKey.PublicKey
clientKey.D.ModInverse(clientKey.D, sm2.OrderN())
return clientKey, clientTempPublicKey, nil
case []byte:
if rnd == nil || len(rnd) < 32 {
return nil, nil, gerrors.WithAnnotating(ErrInvalidInput, "input rnd must be as 32 bytes")
}
clientKey = sm2.NewPrivateKey()
_ = clientKey.SetBytes(rnd)
clientTempPublicKey = sm2.GenPublicKey(clientKey)
clientKey.D.ModInverse(clientKey.D, sm2.OrderN())
err = nil
return
default:
return nil, nil, errors.New("parameter rnd can only be nil, io.Reader or []byte (with length >= 32)")
}
}
/*
serverkey = d2 in [1, n - 1]
publicKey = [d2^(-1)]clientTempPublicKey - G,用户签名公钥P
serverTempPublicKey = [d2^(-1)]G
*/
func ServerGenSignKey(clientTempPublicKey *sm2.PublicKey, rnd []byte) (
serverKey *sm2.PrivateKey,
serverTempPublicKey *sm2.PublicKey,
publicKey *sm2.PublicKey,
err error) {
if rnd == nil || len(rnd) < 32 {
return nil, nil, nil, gerrors.WithAnnotating(ErrInvalidInput, "input rnd must be as 32 bytes")
}
serverKey = sm2.NewPrivateKey()
_ = serverKey.SetBytes(rnd)
serverTempPublicKey = sm2.GenPublicKey(serverKey)
x, y := sm2.Curve256.ScalarMult(clientTempPublicKey.X, clientTempPublicKey.Y, serverKey.D.Bytes())
y.Sub(sm2.Curve().Params().P, y)
x, y = sm2.Curve().Add(x, y, sm2.Curve().Params().Gx, sm2.Curve().Params().Gy)
y.Sub(sm2.Curve().Params().P, y)
publicKey = &sm2.PublicKey{X: x, Y: y}
serverKey.D.ModInverse(serverKey.D, sm2.OrderN())
err = nil
return
}
// ClientGenSignKey_two 客户端对服务端发送来的公钥publicKey和根据clientKey,serverTempPublicKey计算出来的公钥比较。
// 若两者一致,则秘钥生成成功。
func ClientGenSignKey_two(clientKey *sm2.PrivateKey, serverTempPublicKey *sm2.PublicKey, publicKey *sm2.PublicKey) error {
d1Inv := new(big.Int).ModInverse(clientKey.D, sm2.OrderN())
x, y := sm2.Curve256.ScalarMult(serverTempPublicKey.X, serverTempPublicKey.Y, d1Inv.Bytes())
y.Sub(sm2.Curve().Params().P, y)
x, y = sm2.Curve().Add(x, y, sm2.Curve().Params().Gx, sm2.Curve().Params().Gy)
y.Sub(sm2.Curve().Params().P, y)
if x.Cmp(publicKey.X) != 0 || y.Cmp(publicKey.Y) != 0 {
return fmt.Errorf("generate key failed")
}
return nil
}
// realPrivateKey compute the real private key, for test
func realPrivateKey(clientKey, serverKey *sm2.PrivateKey) *sm2.PrivateKey {
d := new(big.Int).Mul(serverKey.D, clientKey.D)
d.ModInverse(d, sm2.OrderN())
d.Sub(d, gmath.BigInt1)
sk := &sm2.PrivateKey{
D: d,
}
sm2.GenPublicKey(sk)
return sk
}