package sm9 import ( "fmt" "io" "math/big" "strings" "xdx.jelly/xgcl/gerrors" "xdx.jelly/xgcl/gmath" "xdx.jelly/xgcl/grand" "xdx.jelly/xgcl/sm/sm3" "xdx.jelly/xgcl/sm/sm9/errors" ) // 38635打印数据 const PrintIntermediaDataForSTD38635 = false // Signature 签名数据结构 type Signature struct { H big.Int S G1 } // NewSignature returns a new Signature. // // Deprecated, use `&Signature{}` or `new(Signature)`. func NewSignature() *Signature { return &Signature{} } // MarshalBinary implements the encoding.BinaryMarshaler interface. It returns the byte slice of H || X || Y. func (s *Signature) MarshalBinary() ([]byte, error) { data := make([]byte, 3*Sm9RefMaxLen) if err := gmath.FillBytes(&s.H, data[:Sm9RefMaxLen]); err != nil { return nil, err } s.S.FillBytes(data[Sm9RefMaxLen:]) return data, nil } // UnmarshalBinary implements the encoding.BinaryUnmarshaler interface // if return error, s will remain func (s *Signature) UnmarshalBinary(data []byte) error { if len(data) != 3*Sm9RefMaxLen { return gerrors.WithAnnotating(errors.ErrInvalidInput, "input data too short") } s.H.SetBytes(data[:Sm9RefMaxLen]) if s.H.Cmp(Order()) >= 0 || s.H.Sign() == 0 { return gerrors.WithAnnotating(errors.ErrInvalidInput, "Signature.H is zero or bigger than order N") } _, err := s.S.Unmarshal(data[Sm9RefMaxLen:]) if err != nil { return gerrors.WithMessage(err, "Signature.S Unmarshal failed") } return nil } // String 实现Stringer接口 func (s *Signature) String() string { return fmt.Sprintf("SM9 Signature{\n\tH: %s,\n\tS: %s\n}", s.H.Text(16), s.S.String()) } // Bytes output H || X || Y func (s *Signature) Bytes() []byte { buf := make([]byte, 3*byteSize) copy(buf[:byteSize], gmath.BigIntToNByte(&s.H, byteSize)) copy(buf[byteSize:], s.S.Marshal()) return buf } func (s *Signature) Set(t *Signature) { s.H.Set(&t.H) s.S.Set(&t.S) } // SetBytes set signature from a byte slice func (s *Signature) SetBytes(data []byte) error { if len(data) < 3*byteSize { return gerrors.WithAnnotating(errors.ErrInvalidInput, "input data too short") } data = data[:3*byteSize] s.H.SetBytes(data[:byteSize]) s.S.Unmarshal(data[byteSize:]) return nil } // Sign 签名 // // rnd输入随机字节串或随机数发生器,可以为: // - []byte, 并且len(rnd)= 32 // - io.Reader, 随机数发生器, 如crypto/rand.Reader, 也可以是包装的硬件随机数发生器 // - nil, 则会使用默认的软件随机数发生器 func Sign(msg []byte, ds *UserSignKey, pubs *MastSignPublicKey, rnd interface{}) (*Signature, error) { if rnd == nil { rnd = grand.Reader } if b, ok := rnd.([]byte); ok { return sign(msg, ds, pubs, b) } else if reader, ok := rnd.(io.Reader); ok { b := make([]byte, numBytes) if _, err := reader.Read(b); err != nil { return nil, gerrors.ChainErrors(errors.ErrSignFailed, err) } return sign(msg, ds, pubs, b) } else { return nil, gerrors.WithAnnotating(errors.ErrSignFailed, "input rnd can only be nil, []byte or io.Reader") } } func sign(msg []byte, ds *UserSignKey, pubs *MastSignPublicKey, rnd []byte) (*Signature, error) { if len(rnd) != byteSize { return nil, gerrors.WithAnnotating(errors.ErrInvalidInput, "input rnd too short") } signature := &Signature{} r := new(big.Int) h := new(big.Int) g := >{} for { r.SetBytes(rnd[:byteSize]) if pubs.e != nil { g.ScalarMult(pubs.e, r) } else { mulG1BaseThenPairing(g, &pubs.G2, r) } h = H2(msg, g.Marshal()) r.Sub(r, h) r.Mod(r, Order()) if PrintIntermediaDataForSTD38635 { fmt.Printf("计算群GT中的元素g = e (P1 , Ppub-s): %s\n", pubs.e.String()) fmt.Printf("计算群GT中的元素w = g^r: %s\n", g.String()) fmt.Printf("h: %s\n", strings.ToUpper(h.Text(16))) fmt.Printf("计算l = ( r - h ) mod N: %s\n", strings.ToUpper(r.Text(16))) } if r.Sign() != 0 { break } d := sm3.Sum(rnd) copy(rnd, d[:]) } // Issues 5 // s := ds.G1.ScalarMult(&ds.G1, r) //ds changed! s := (&G1{}).ScalarMult(&ds.G1, r) if PrintIntermediaDataForSTD38635 { fmt.Printf("计算群G1中的元素S: %s\n", s.String()) fmt.Printf("消息M的签名为(h, S):\n") fmt.Printf("h: %s\n", strings.ToUpper(h.Text(16))) fmt.Printf("S: %s\n", s.String()) } signature.H.Set(h) signature.S.Set(s) return signature, nil } // Verify 签名验证 func Verify(sig *Signature, uid, msg []byte, pubs *MastSignPublicKey) bool { h := new(big.Int).Set(&sig.H) if gmath.IsBigInt0(h) || h.Cmp(Order()) >= 0 { return false } if !sig.S.IsValid() || sig.S.IsZero() { return false } t := >{} mulG1BaseThenPairing(t, &pubs.G2, h) h1 := H1(uid, []byte{hidSign}) p := new(G2).ScalarBaseMult(h1) p.Add(p, &pubs.G2) u := >{} pairing(u, &sig.S, p) if PrintIntermediaDataForSTD38635 { fmt.Printf("计算群GT中的元素g = e (P1 , Ppub-s): %s\n", pubs.e.String()) fmt.Printf("计算群GT中的元素t = g^h: %s\n", t.String()) fmt.Printf("计算h1 = H1(IDA||hid, N)\n") fmt.Printf("h1: %s\n", strings.ToUpper(h1.Text(16))) fmt.Printf("计算群G2中的元素P = [h1]P2 + Ppub-s = (xP , yP): %s\n", p.String()) fmt.Printf("计算群GT中的元素u = e (S , P): %s\n", u.String()) } u.Add(u, t) // In GT, Add is the same with Mul h2 := H2(msg, u.Marshal()) if PrintIntermediaDataForSTD38635 { fmt.Printf("计算群GT中的元素w' = u*t: %s\n", u.String()) fmt.Printf("计算h2 = H2(M||w, N): %s\n", strings.ToUpper(h.Text(16))) } return h2.Cmp(h) == 0 }