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 }