package sm9 import ( "errors" "io" "math/big" ) // G2 is an abstract cyclic group. The zero value is suitable for use as the // output of an operation, but cannot be used as an input. type G2 struct { p *twistPoint } //Gen2 is the generator of G2. var Gen2 = &G2{twistGen} // RandomG2 returns x and g₂ˣ where x is a random, non-zero number read from r. func RandomG2(r io.Reader) (*big.Int, *G2, error) { k, err := randomK(r) if err != nil { return nil, nil, err } return k, new(G2).ScalarBaseMult(k), nil } func (e *G2) String() string { return "sm9.G2" + e.p.String() } // ScalarBaseMult sets e to g*k where g is the generator of the group and then // returns out. func (e *G2) ScalarBaseMult(k *big.Int) *G2 { if e.p == nil { e.p = &twistPoint{} } e.p.Mul(twistGen, k) return e } // ScalarMult sets e to a*k and then returns e. func (e *G2) ScalarMult(a *G2, k *big.Int) *G2 { if e.p == nil { e.p = &twistPoint{} } e.p.Mul(a.p, k) return e } // Add sets e to a+b and then returns e. func (e *G2) Add(a, b *G2) *G2 { if e.p == nil { e.p = &twistPoint{} } e.p.Add(a.p, b.p) return e } // Neg sets e to -a and then returns e. func (e *G2) Neg(a *G2) *G2 { if e.p == nil { e.p = &twistPoint{} } e.p.Neg(a.p) return e } // Set sets e to a and then returns e. func (e *G2) Set(a *G2) *G2 { if e.p == nil { e.p = &twistPoint{} } e.p.Set(a.p) return e } // Marshal converts e into a byte slice. func (e *G2) Marshal() []byte { // Each value is a 256-bit number. const numBytes = 256 / 8 ret := make([]byte, numBytes*4) e.fillBytes(ret) return ret } // Marshal converts e into a byte slice with prefix func (e *G2) MarshalUncompressed() []byte { // Each value is a 256-bit number. const numBytes = 256 / 8 ret := make([]byte, numBytes*4+1) ret[0] = 4 e.fillBytes(ret[1:]) return ret } func (e *G2) fillBytes(buffer []byte) { // Each value is a 256-bit number. const numBytes = 256 / 8 if e.p == nil { e.p = &twistPoint{} } e.p.MakeAffine() if e.p.IsInfinity() { return } temp := &gfP{} montDecode(temp, &e.p.x.x) temp.Marshal(buffer) montDecode(temp, &e.p.x.y) temp.Marshal(buffer[numBytes:]) montDecode(temp, &e.p.y.x) temp.Marshal(buffer[2*numBytes:]) montDecode(temp, &e.p.y.y) temp.Marshal(buffer[3*numBytes:]) } // Unmarshal sets e to the result of converting the output of Marshal back into // a group element and then returns e. func (e *G2) Unmarshal(m []byte) ([]byte, error) { // Each value is a 256-bit number. const numBytes = 256 / 8 if len(m) < 4*numBytes { return nil, errors.New("sm9.G2: not enough data") } // Unmarshal the points and check their caps if e.p == nil { e.p = &twistPoint{} } var err error if err = e.p.x.x.Unmarshal(m); err != nil { return nil, err } if err = e.p.x.y.Unmarshal(m[numBytes:]); err != nil { return nil, err } if err = e.p.y.x.Unmarshal(m[2*numBytes:]); err != nil { return nil, err } if err = e.p.y.y.Unmarshal(m[3*numBytes:]); err != nil { return nil, err } // Encode into Montgomery form and ensure it's on the curve montEncode(&e.p.x.x, &e.p.x.x) montEncode(&e.p.x.y, &e.p.x.y) montEncode(&e.p.y.x, &e.p.y.x) montEncode(&e.p.y.y, &e.p.y.y) if e.p.x.IsZero() && e.p.y.IsZero() { // This is the point at infinity. e.p.y.SetOne() e.p.z.SetZero() e.p.t.SetZero() } else { e.p.z.SetOne() e.p.t.SetOne() if !e.p.IsOnCurve() { return nil, errors.New("sm9.G2: malformed point") } } return m[4*numBytes:], nil }