init: v1.0.0

This commit is contained in:
yaole
2026-05-27 23:03:00 +08:00
commit 8d97f750eb
466 changed files with 80067 additions and 0 deletions
+281
View File
@@ -0,0 +1,281 @@
package sm2
import (
"crypto/rand"
"encoding/hex"
"math/big"
"strings"
"golang.org/x/crypto/cryptobyte"
"golang.org/x/crypto/cryptobyte/asn1"
"xdx.jelly/xgcl/gerrors"
"xdx.jelly/xgcl/gmath"
"xdx.jelly/xgcl/sm/sm2/ec256"
"xdx.jelly/xgcl/sm/sm3"
)
// Signature 签名结构体
type Signature struct {
R, S *big.Int
}
// NewSignature .
func NewSignature() *Signature {
return &Signature{
R: new(big.Int),
S: new(big.Int),
}
}
// MarshalUtil implements the gcl/util/encoding/UtilMarshaler interface
func (sig *Signature) MarshalUtil(data []byte) ([]byte, error) {
if data == nil {
data = make([]byte, 0, 2*ECCRefMaxLen)
}
sig.R.Mod(sig.R, orderN)
sig.S.Mod(sig.S, orderN)
data = append(data, gmath.BigIntToNByte(sig.R, ECCRefMaxLen)...)
data = append(data, gmath.BigIntToNByte(sig.S, ECCRefMaxLen)...)
return data, nil
}
func (sig *Signature) UnmarshalUtil(data []byte) (uint64, error) {
n := uint64(0)
if len(data) < 2*ECCRefMaxLen {
return 0, gerrors.WithAnnotating(ErrInvalidInput, "input data too short")
}
r := new(big.Int).SetBytes(data[:ECCRefMaxLen])
data = data[ECCRefMaxLen:]
n += ECCRefMaxLen
if r.Cmp(orderN) >= 0 || r.Sign() == 0 {
return 0, gerrors.WithAnnotating(ErrInvalidInput, "r is zero or bigger than the order N")
}
s := new(big.Int).SetBytes(data[:ECCRefMaxLen])
data = data[ECCRefMaxLen:]
n += ECCRefMaxLen
if s.Cmp(orderN) >= 0 || s.Sign() == 0 {
return 0, gerrors.WithAnnotating(ErrInvalidInput, "s is zero or bigger than the order N")
}
sig.R.Set(r)
sig.S.Set(s)
return n, nil
}
// MarshalBinary implements the encoding.BinaryMarshaler interface
// r || s
func (sig *Signature) MarshalBinary() ([]byte, error) {
data := make([]byte, 2*ECCRefMaxLen)
sig.R.Mod(sig.R, orderN)
sig.S.Mod(sig.S, orderN)
rBytes := sig.R.Bytes()
copy(data[ECCRefMaxLen-len(rBytes):], rBytes)
sBytes := sig.S.Bytes()
copy(data[2*ECCRefMaxLen-len(sBytes):], sBytes)
return data, nil
}
// UnmarshalBinary implements the encoding.BinaryUnmarshaler interface
func (sig *Signature) UnmarshalBinary(data []byte) error {
if len(data) != 2*ECCRefMaxLen {
return gerrors.WithAnnotating(ErrInvalidInput, "input data too short")
}
r := new(big.Int).SetBytes(data[:ECCRefMaxLen])
if r.Cmp(orderN) >= 0 || r.Sign() == 0 {
return gerrors.WithAnnotating(ErrInvalidInput, "r is zero or bigger than the order N")
}
s := new(big.Int).SetBytes(data[ECCRefMaxLen : 2*ECCRefMaxLen])
if s.Cmp(orderN) >= 0 || s.Sign() == 0 {
return gerrors.WithAnnotating(ErrInvalidInput, "s is zero or bigger than the order N")
}
sig.R.Set(r)
sig.S.Set(s)
return nil
}
func (sig *Signature) MarshalASN1() ([]byte, error) {
var b cryptobyte.Builder
b.AddASN1(asn1.SEQUENCE, func(b *cryptobyte.Builder) {
b.AddASN1BigInt(sig.R)
b.AddASN1BigInt(sig.S)
})
return b.Bytes()
}
func (sig *Signature) UnmarshalASN1(data []byte) error {
if sig.R == nil {
sig.R = new(big.Int)
}
if sig.S == nil {
sig.S = new(big.Int)
}
var inner cryptobyte.String
input := cryptobyte.String(data)
if !input.ReadASN1(&inner, asn1.SEQUENCE) ||
!input.Empty() ||
!inner.ReadASN1Integer(sig.R) ||
!inner.ReadASN1Integer(sig.S) ||
!inner.Empty() {
return ErrDecodeASN1Failed
}
return nil
}
// SetBytes set Signature from a byte slice
func (sig *Signature) SetBytes(rs []byte) error {
if len(rs) < 2*byteSize {
return gerrors.WithAnnotating(ErrInvalidInput, "input data too short")
}
if sig.R == nil {
sig.R = new(big.Int)
}
if sig.S == nil {
sig.S = new(big.Int)
}
sig.R.SetBytes(rs[:byteSize])
sig.S.SetBytes(rs[byteSize : 2*byteSize])
return nil
}
// Bytes return byte slice of a signature
func (sig *Signature) Bytes() []byte {
buf := make([]byte, 2*byteSize)
_ = gmath.FillBytes(sig.R, buf[:byteSize])
_ = gmath.FillBytes(sig.S, buf[byteSize:])
return buf
}
// String return a readable string
func (sig *Signature) String() string {
var buf strings.Builder
buf.WriteString("r: ")
buf.WriteString(hex.EncodeToString(gmath.BigIntToNByte(sig.R, ECCRefMaxLen)))
buf.WriteString("\ns: ")
buf.WriteString(hex.EncodeToString(gmath.BigIntToNByte(sig.S, ECCRefMaxLen)))
return buf.String()
}
// update a random k in case when Sign got a random integer k error
// k's address are unchanged
func update(k []byte) {
hash := sm3.Sum(k)
copy(k, hash[:])
}
// fermatInverse calculates the inverse of k in GF(P) using Fermat's method.
// This has better constant-time properties than Euclid's method (implemented
// in math/big.Int.ModInverse) although math/big itself isn't strictly
// constant-time so it's not perfect.
// k = k^{-1} mod N
func fermatInverse(k, N *big.Int) {
// two := big.NewInt(2)
nMinus2 := new(big.Int)
nMinus2.Sub(N, gmath.BigInt2)
k.Exp(k, nMinus2, N)
}
// Sign 签名
// e: sm3(Z || M),使用PreComputeWithIdAndPubkeyAndMessage计算
// k: 32字节随机数
func Sign(e, k []byte, privateKey *PrivateKey) (*Signature, error) {
if len(e) < byteSize {
return nil, gerrors.WithAnnotatingf(ErrInvalidInput, "input e should be of %d bytes, but it is %d bytes", byteSize, len(e))
}
if len(k) < byteSize {
return nil, gerrors.WithAnnotatingf(ErrInvalidInput, "input k should be of %d bytes, but it is %d bytes", byteSize, len(k))
}
r := new(big.Int).SetBytes(e[:byteSize])
s := new(big.Int)
intK := new(big.Int)
// for only loop one time for almost all case
for {
intK.SetBytes(k[:byteSize])
if intK.Cmp(orderN) >= 0 {
intK.Sub(intK, orderN)
}
if intK.Sign() == 0 {
// omit the return error cause nMinusOne > 0
intK, _ = rand.Int(rand.Reader, nMinusOne)
}
// ScalarBaseMult is in constant-time
x1, _ := sm2Curve.ScalarBaseMult(intK.Bytes())
r.Add(x1, r) // r = x1 + e
r.Mod(r, orderN)
// rearly happen
if gmath.IsBigInt0(r) {
goto Next
}
// s = (1+d)^(-1)(k + r - r - r*d)=(1+d)^(-1) * (k+r) - r
s.Add(privateKey.D, gmath.BigInt1)
// invert s mod N costs much time
if f, ok := sm2Curve.(interface{ Inverse(*big.Int) *big.Int }); ok {
s = f.Inverse(s)
} else {
// s.ModInverse(s, orderN)
fermatInverse(s, orderN)
}
intK.Add(intK, r)
// k + r < 2N and k + r > N is the most likely case
if cmpResult := intK.Cmp(orderN); cmpResult > 0 {
intK.Sub(intK, orderN)
} else if cmpResult == 0 {
goto Next
}
s.Mul(s, intK)
s.Sub(s, r)
s.Mod(s, orderN)
break
Next:
// for another random k
update(k[:byteSize])
continue
}
return &Signature{R: r, S: s}, nil
}
// Verify 验签
// pk:公钥,不做验证pk是否有效,另调用pk.IsValid()判断pk是否是在曲线上。
//
// 当然如果pk无效,返回false
//
// e: sm3(Z || M),使用PreComputeWithIdAndPubkeyAndMessage计算
func Verify(e []byte, pk *PublicKey, sig *Signature) bool {
if len(e) != byteSize {
return false
}
r := sig.R
s := sig.S
if r.Sign() <= 0 || s.Sign() <= 0 ||
r.Cmp(orderN) >= 0 || s.Cmp(orderN) >= 0 {
return false
}
x := pk.X
y := pk.Y
t := new(big.Int).Add(r, s)
var x1, y1 *big.Int
if false {
t.Mod(t, orderN)
x1, y1 = sm2Curve.ScalarBaseMult(sig.S.Bytes())
x2, y2 := sm2Curve.ScalarMult(x, y, t.Bytes())
x1, _ = sm2Curve.Add(x1, y1, x2, y2)
} else {
x1, _ = ec256.CombinedMult(x, y, sig.S.Bytes(), t.Bytes())
}
t.SetBytes(e)
x1.Add(x1, t)
x1.Mod(x1, orderN)
return x1.Cmp(r) == 0
}