diff --git a/driver/amcl/fp256bn.go b/driver/amcl/fp256bn.go index 4926635..2029917 100644 --- a/driver/amcl/fp256bn.go +++ b/driver/amcl/fp256bn.go @@ -202,6 +202,11 @@ func (e *fp256bnG1) Mul2(ee driver.Zr, Q driver.G1, f driver.Zr) driver.G1 { return &fp256bnG1{*e.ECP.Mul2(bigToMiraclBIGCore(&ee.(*common.BaseZr).Int), &Q.(*fp256bnG1).ECP, bigToMiraclBIGCore(&f.(*common.BaseZr).Int))} } +func (e *fp256bnG1) Mul2InPlace(ee driver.Zr, Q driver.G1, f driver.Zr) { + v := e.ECP.Mul2(bigToMiraclBIGCore(&ee.(*common.BaseZr).Int), &Q.(*fp256bnG1).ECP, bigToMiraclBIGCore(&f.(*common.BaseZr).Int)) + e.ECP = *v +} + func (e *fp256bnG1) Equals(a driver.G1) bool { return e.ECP.Equals(&a.(*fp256bnG1).ECP) } diff --git a/driver/amcl/fp256bn_miracl.go b/driver/amcl/fp256bn_miracl.go index c17e9c9..dadb7f6 100644 --- a/driver/amcl/fp256bn_miracl.go +++ b/driver/amcl/fp256bn_miracl.go @@ -204,6 +204,10 @@ func (e *fp256bnMiraclG1) Mul2(ee driver.Zr, Q driver.G1, f driver.Zr) driver.G1 return &fp256bnMiraclG1{*e.ECP.Mul2(bigToMiraclBIG(&ee.(*common.BaseZr).Int), &Q.(*fp256bnMiraclG1).ECP, bigToMiraclBIG(&f.(*common.BaseZr).Int))} } +func (e *fp256bnMiraclG1) Mul2InPlace(ee driver.Zr, Q driver.G1, f driver.Zr) { + e.ECP = *e.ECP.Mul2(bigToMiraclBIG(&ee.(*common.BaseZr).Int), &Q.(*fp256bnMiraclG1).ECP, bigToMiraclBIG(&f.(*common.BaseZr).Int)) +} + func (e *fp256bnMiraclG1) Equals(a driver.G1) bool { return e.ECP.Equals(&a.(*fp256bnMiraclG1).ECP) } diff --git a/driver/common/big.go b/driver/common/big.go index 5eaf9f3..15fd21e 100644 --- a/driver/common/big.go +++ b/driver/common/big.go @@ -75,6 +75,10 @@ func (b *BaseZr) InvModP(p driver.Zr) { b.Int.ModInverse(&b.Int, &p.(*BaseZr).Int) } +func (b *BaseZr) InvModOrder() { + b.Int.ModInverse(&b.Int, &b.Modulus) +} + func (b *BaseZr) Bytes() []byte { target := b.Int diff --git a/driver/common/curve.go b/driver/common/curve.go index cb65333..07d7d9d 100644 --- a/driver/common/curve.go +++ b/driver/common/curve.go @@ -88,3 +88,15 @@ func (c *CurveBase) HashToZr(data []byte) driver.Zr { func (p *CurveBase) Rand() (io.Reader, error) { return rand.Reader, nil } + +func (p *CurveBase) ModAddMul(a1 []driver.Zr, b1 []driver.Zr, modulo driver.Zr) driver.Zr { + sum := p.NewZrFromInt64(0) + for i := 0; i < len(a1); i++ { + sum = p.ModAdd(sum, p.ModMul(a1[i], b1[i], modulo), modulo) + } + return sum +} + +func (p *CurveBase) ModAddMul2(a1 driver.Zr, c1 driver.Zr, b1 driver.Zr, c2 driver.Zr, m driver.Zr) driver.Zr { + return p.ModAdd(p.ModMul(a1, c1, m), p.ModMul(b1, c2, m), m) +} diff --git a/driver/gurvy/bls12-377.go b/driver/gurvy/bls12-377.go index ec40aac..e855612 100644 --- a/driver/gurvy/bls12-377.go +++ b/driver/gurvy/bls12-377.go @@ -58,6 +58,14 @@ func (g *bls12377G1) Mul2(e driver.Zr, Q driver.G1, f driver.Zr) driver.G1 { return a } +func (g *bls12377G1) Mul2InPlace(e driver.Zr, Q driver.G1, f driver.Zr) { + a := g.Mul(e) + b := Q.Mul(f) + a.Add(b) + + g.Set(&a.(*bls12377G1).G1Affine) +} + func (g *bls12377G1) Equals(a driver.G1) bool { return g.G1Affine.Equal(&a.(*bls12377G1).G1Affine) } diff --git a/driver/gurvy/bls12-381.go b/driver/gurvy/bls12-381.go deleted file mode 100644 index 6733f04..0000000 --- a/driver/gurvy/bls12-381.go +++ /dev/null @@ -1,444 +0,0 @@ -/* -Copyright IBM Corp. All Rights Reserved. - -SPDX-License-Identifier: Apache-2.0 -*/ - -package gurvy - -import ( - "fmt" - "hash" - "strings" - - "github.com/IBM/mathlib/driver" - "github.com/IBM/mathlib/driver/common" - bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" - "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" - "golang.org/x/crypto/blake2b" -) - -/*********************************************************************/ - -type bls12381G1 struct { - bls12381.G1Affine -} - -func (g *bls12381G1) Clone(a driver.G1) { - raw := a.(*bls12381G1).G1Affine.Bytes() - _, err := g.SetBytes(raw[:]) - if err != nil { - panic("could not copy point") - } -} - -func (e *bls12381G1) Copy() driver.G1 { - c := &bls12381G1{} - c.Set(&e.G1Affine) - return c -} - -func (g *bls12381G1) Add(a driver.G1) { - j := bls12381.G1Jac{} - j.FromAffine(&g.G1Affine) - j.AddMixed((*bls12381.G1Affine)(&a.(*bls12381G1).G1Affine)) - g.G1Affine.FromJacobian(&j) -} - -func (g *bls12381G1) Mul(a driver.Zr) driver.G1 { - gc := &bls12381G1{} - gc.G1Affine.ScalarMultiplication(&g.G1Affine, &a.(*common.BaseZr).Int) - - return gc -} - -func (g *bls12381G1) Mul2(e driver.Zr, Q driver.G1, f driver.Zr) driver.G1 { - a := g.Mul(e) - b := Q.Mul(f) - a.Add(b) - - return a -} - -func (g *bls12381G1) Equals(a driver.G1) bool { - return g.G1Affine.Equal(&a.(*bls12381G1).G1Affine) -} - -func (g *bls12381G1) Bytes() []byte { - raw := g.G1Affine.RawBytes() - return raw[:] -} - -func (g *bls12381G1) Compressed() []byte { - raw := g.G1Affine.Bytes() - return raw[:] -} - -func (g *bls12381G1) Sub(a driver.G1) { - j, k := bls12381.G1Jac{}, bls12381.G1Jac{} - j.FromAffine(&g.G1Affine) - k.FromAffine(&a.(*bls12381G1).G1Affine) - j.SubAssign(&k) - g.G1Affine.FromJacobian(&j) -} - -func (g *bls12381G1) IsInfinity() bool { - return g.G1Affine.IsInfinity() -} - -func (g *bls12381G1) String() string { - rawstr := g.G1Affine.String() - m := g1StrRegexp.FindAllStringSubmatch(rawstr, -1) - return "(" + strings.TrimLeft(m[0][1], "0") + "," + strings.TrimLeft(m[0][2], "0") + ")" -} - -func (g *bls12381G1) Neg() { - g.G1Affine.Neg(&g.G1Affine) -} - -/*********************************************************************/ - -type bls12381G2 struct { - bls12381.G2Affine -} - -func (g *bls12381G2) Clone(a driver.G2) { - raw := a.(*bls12381G2).G2Affine.Bytes() - _, err := g.SetBytes(raw[:]) - if err != nil { - panic("could not copy point") - } -} - -func (e *bls12381G2) Copy() driver.G2 { - c := &bls12381G2{} - c.Set(&e.G2Affine) - return c -} - -func (g *bls12381G2) Mul(a driver.Zr) driver.G2 { - gc := &bls12381G2{} - gc.G2Affine.ScalarMultiplication(&g.G2Affine, &a.(*common.BaseZr).Int) - - return gc -} - -func (g *bls12381G2) Add(a driver.G2) { - j := bls12381.G2Jac{} - j.FromAffine(&g.G2Affine) - j.AddMixed((*bls12381.G2Affine)(&a.(*bls12381G2).G2Affine)) - g.G2Affine.FromJacobian(&j) -} - -func (g *bls12381G2) Sub(a driver.G2) { - j := bls12381.G2Jac{} - j.FromAffine(&g.G2Affine) - aJac := bls12381.G2Jac{} - aJac.FromAffine((*bls12381.G2Affine)(&a.(*bls12381G2).G2Affine)) - j.SubAssign(&aJac) - g.G2Affine.FromJacobian(&j) -} - -func (g *bls12381G2) Affine() { - // we're always affine -} - -func (g *bls12381G2) Bytes() []byte { - raw := g.G2Affine.RawBytes() - return raw[:] -} - -func (g *bls12381G2) Compressed() []byte { - raw := g.G2Affine.Bytes() - return raw[:] -} - -func (g *bls12381G2) String() string { - return g.G2Affine.String() -} - -func (g *bls12381G2) Equals(a driver.G2) bool { - return g.G2Affine.Equal(&a.(*bls12381G2).G2Affine) -} - -/*********************************************************************/ - -type bls12381Gt struct { - bls12381.GT -} - -func (g *bls12381Gt) Exp(x driver.Zr) driver.Gt { - copy := bls12381.GT{} - return &bls12381Gt{*copy.Exp(g.GT, &x.(*common.BaseZr).Int)} -} - -func (g *bls12381Gt) Equals(a driver.Gt) bool { - return g.GT.Equal(&a.(*bls12381Gt).GT) -} - -func (g *bls12381Gt) Inverse() { - g.GT.Inverse(&g.GT) -} - -func (g *bls12381Gt) Mul(a driver.Gt) { - g.GT.Mul(&g.GT, &a.(*bls12381Gt).GT) -} - -func (g *bls12381Gt) IsUnity() bool { - unity := bls12381.GT{} - unity.SetOne() - - return unity.Equal(&g.GT) -} - -func (g *bls12381Gt) ToString() string { - return g.GT.String() -} - -func (g *bls12381Gt) Bytes() []byte { - raw := g.GT.Bytes() - return raw[:] -} - -/*********************************************************************/ - -func NewBls12_381() *Bls12_381 { - return &Bls12_381{common.CurveBase{Modulus: *fr.Modulus()}} -} - -func NewBls12_381BBS() *Bls12_381BBS { - return &Bls12_381BBS{*NewBls12_381()} -} - -type Bls12_381 struct { - common.CurveBase -} - -type Bls12_381BBS struct { - Bls12_381 -} - -func (c *Bls12_381) Pairing(p2 driver.G2, p1 driver.G1) driver.Gt { - t, err := bls12381.MillerLoop([]bls12381.G1Affine{p1.(*bls12381G1).G1Affine}, []bls12381.G2Affine{p2.(*bls12381G2).G2Affine}) - if err != nil { - panic(fmt.Sprintf("pairing failed [%s]", err.Error())) - } - - return &bls12381Gt{t} -} - -func (c *Bls12_381) Pairing2(p2a, p2b driver.G2, p1a, p1b driver.G1) driver.Gt { - t, err := bls12381.MillerLoop([]bls12381.G1Affine{p1a.(*bls12381G1).G1Affine, p1b.(*bls12381G1).G1Affine}, []bls12381.G2Affine{p2a.(*bls12381G2).G2Affine, p2b.(*bls12381G2).G2Affine}) - if err != nil { - panic(fmt.Sprintf("pairing 2 failed [%s]", err.Error())) - } - - return &bls12381Gt{t} -} - -func (c *Bls12_381) FExp(a driver.Gt) driver.Gt { - return &bls12381Gt{bls12381.FinalExponentiation(&a.(*bls12381Gt).GT)} -} - -var g1Bytes12_381 [48]byte -var g2Bytes12_381 [96]byte - -func init() { - _, _, g1, g2 := bls12381.Generators() - g1Bytes12_381 = g1.Bytes() - g2Bytes12_381 = g2.Bytes() -} - -func (c *Bls12_381) GenG1() driver.G1 { - r := &bls12381G1{} - _, err := r.SetBytes(g1Bytes12_381[:]) - if err != nil { - panic("could not generate point") - } - - return r -} - -func (c *Bls12_381) GenG2() driver.G2 { - r := &bls12381G2{} - _, err := r.SetBytes(g2Bytes12_381[:]) - if err != nil { - panic("could not generate point") - } - - return r -} - -func (c *Bls12_381) GenGt() driver.Gt { - g1 := c.GenG1() - g2 := c.GenG2() - gengt := c.Pairing(g2, g1) - gengt = c.FExp(gengt) - return gengt -} - -func (c *Bls12_381) CoordinateByteSize() int { - return bls12381.SizeOfG1AffineCompressed -} - -func (c *Bls12_381) G1ByteSize() int { - return bls12381.SizeOfG1AffineUncompressed -} - -func (c *Bls12_381) CompressedG1ByteSize() int { - return bls12381.SizeOfG1AffineCompressed -} - -func (c *Bls12_381) G2ByteSize() int { - return bls12381.SizeOfG2AffineUncompressed -} - -func (c *Bls12_381) CompressedG2ByteSize() int { - return bls12381.SizeOfG2AffineCompressed -} - -func (c *Bls12_381) ScalarByteSize() int { - return common.ScalarByteSize -} - -func (c *Bls12_381) NewG1() driver.G1 { - return &bls12381G1{} -} - -func (c *Bls12_381) NewG2() driver.G2 { - return &bls12381G2{} -} - -func (c *Bls12_381) NewG1FromBytes(b []byte) driver.G1 { - v := &bls12381G1{} - _, err := v.G1Affine.SetBytes(b) - if err != nil { - panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) - } - - return v -} - -func (c *Bls12_381) NewG2FromBytes(b []byte) driver.G2 { - v := &bls12381G2{} - _, err := v.SetBytes(b) - if err != nil { - panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) - } - - return v -} - -func (c *Bls12_381) NewG1FromCompressed(b []byte) driver.G1 { - v := &bls12381G1{} - _, err := v.SetBytes(b) - if err != nil { - panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) - } - - return v -} - -func (c *Bls12_381) NewG2FromCompressed(b []byte) driver.G2 { - v := &bls12381G2{} - _, err := v.SetBytes(b) - if err != nil { - panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) - } - - return v -} - -func (c *Bls12_381) NewGtFromBytes(b []byte) driver.Gt { - v := &bls12381Gt{} - err := v.SetBytes(b) - if err != nil { - panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) - } - - return v -} - -func (c *Bls12_381) HashToG1(data []byte) driver.G1 { - g1, err := bls12381.HashToG1(data, []byte{}) - if err != nil { - panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) - } - - return &bls12381G1{g1} -} - -func (c *Bls12_381) HashToG2(data []byte) driver.G2 { - g2, err := bls12381.HashToG2(data, []byte{}) - if err != nil { - panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) - } - - return &bls12381G2{g2} -} - -func (p *Bls12_381) HashToG1WithDomain(data, domain []byte) driver.G1 { - g1, err := bls12381.HashToG1(data, domain) - if err != nil { - panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) - } - - return &bls12381G1{g1} -} - -func (p *Bls12_381) HashToG2WithDomain(data, domain []byte) driver.G2 { - g2, err := bls12381.HashToG2(data, domain) - if err != nil { - panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) - } - - return &bls12381G2{g2} -} - -func (c *Bls12_381BBS) HashToG1(data []byte) driver.G1 { - hashFunc := func() hash.Hash { - // We pass a null key so error is impossible here. - h, _ := blake2b.New512(nil) //nolint:errcheck - return h - } - - g1, err := HashToG1GenericBESwu(data, []byte{}, hashFunc) - if err != nil { - panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) - } - - return &bls12381G1{g1} -} - -func (c *Bls12_381BBS) HashToG2(data []byte) driver.G2 { - g2, err := bls12381.HashToG2(data, []byte{}) - if err != nil { - panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) - } - - return &bls12381G2{g2} -} - -func (p *Bls12_381BBS) HashToG1WithDomain(data, domain []byte) driver.G1 { - hashFunc := func() hash.Hash { - // We pass a null key so error is impossible here. - h, _ := blake2b.New512(nil) //nolint:errcheck - return h - } - - g1, err := HashToG1GenericBESwu(data, domain, hashFunc) - if err != nil { - panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) - } - - return &bls12381G1{g1} -} - -func (p *Bls12_381BBS) HashToG2WithDomain(data, domain []byte) driver.G2 { - g2, err := bls12381.HashToG2(data, domain) - if err != nil { - panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) - } - - return &bls12381G2{g2} -} diff --git a/driver/gurvy/bls12381/bls12-381.go b/driver/gurvy/bls12381/bls12-381.go new file mode 100644 index 0000000..71a1322 --- /dev/null +++ b/driver/gurvy/bls12381/bls12-381.go @@ -0,0 +1,781 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package bls12381 + +import ( + "crypto/rand" + "crypto/sha256" + "fmt" + "hash" + "io" + "math/big" + "regexp" + "strings" + + "github.com/IBM/mathlib/driver" + "github.com/IBM/mathlib/driver/common" + "github.com/IBM/mathlib/driver/gurvy" + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" + "golang.org/x/crypto/blake2b" +) + +var g1StrRegexp = regexp.MustCompile(`^E\([[]([0-9]+),([0-9]+)[]]\)$`) +var g1Bytes12_381 [48]byte +var g2Bytes12_381 [96]byte + +// point at infinity +var g1Infinity bls12381.G1Jac + +func init() { + _, _, g1, g2 := bls12381.Generators() + g1Bytes12_381 = g1.Bytes() + g2Bytes12_381 = g2.Bytes() + g1Infinity.X.SetOne() + g1Infinity.Y.SetOne() +} + +type Zr struct { + big.Int + Modulus big.Int +} + +func (b *Zr) Plus(a driver.Zr) driver.Zr { + rv := &Zr{Modulus: b.Modulus} + rv.Add(&b.Int, &a.(*Zr).Int) + return rv +} + +func (b *Zr) Minus(a driver.Zr) driver.Zr { + rv := &Zr{Modulus: b.Modulus} + rv.Sub(&b.Int, &a.(*Zr).Int) + return rv +} + +func (b *Zr) Mul(a driver.Zr) driver.Zr { + rv := &Zr{Modulus: b.Modulus} + rv.Int.Mul(&b.Int, &a.(*Zr).Int) + rv.Int.Mod(&rv.Int, &b.Modulus) + return rv +} + +func (b *Zr) PowMod(x driver.Zr) driver.Zr { + fr := frElements.Get() + defer frElements.Put(fr) + + fr.SetBigInt(&b.Int) + fr.Exp(*fr, &x.(*Zr).Int) + + rv := &Zr{Modulus: b.Modulus} + fr.BigInt(&rv.Int) + return rv +} + +func (b *Zr) Mod(a driver.Zr) { + b.Int.Mod(&b.Int, &a.(*Zr).Int) +} + +func (b *Zr) InvModP(p driver.Zr) { + b.Int.ModInverse(&b.Int, &p.(*Zr).Int) +} + +func (b *Zr) InvModOrder() { + fr := frElements.Get() + defer frElements.Put(fr) + fr.SetBigInt(&b.Int) + fr.Inverse(fr) + fr.BigInt(&b.Int) +} + +func (b *Zr) Bytes() []byte { + target := b.Int + + if b.Int.Sign() < 0 || b.Int.Cmp(&b.Modulus) > 0 { + target = *new(big.Int).Set(&b.Int) + target = *target.Mod(&target, &b.Modulus) + if target.Sign() < 0 { + target = *target.Add(&target, &b.Modulus) + } + } + + return common.BigToBytes(&target) +} + +func (b *Zr) Equals(p driver.Zr) bool { + return b.Int.Cmp(&p.(*Zr).Int) == 0 +} + +func (b *Zr) Copy() driver.Zr { + rv := &Zr{Modulus: b.Modulus} + rv.Set(&b.Int) + return rv +} + +func (b *Zr) Clone(a driver.Zr) { + raw := a.(*Zr).Int.Bytes() + b.Int.SetBytes(raw) +} + +func (b *Zr) String() string { + return b.Int.Text(16) +} + +func (b *Zr) Neg() { + b.Int.Neg(&b.Int) +} + +/*********************************************************************/ + +type G1 struct { + bls12381.G1Affine +} + +func (g *G1) Clone(a driver.G1) { + raw := a.(*G1).G1Affine.Bytes() + _, err := g.SetBytes(raw[:]) + if err != nil { + panic("could not copy point") + } +} + +func (e *G1) Copy() driver.G1 { + c := &G1{} + c.Set(&e.G1Affine) + return c +} + +func (g *G1) Add(a driver.G1) { + j := G1Jacs.Get() + defer G1Jacs.Put(j) + j.FromAffine(&g.G1Affine) + j.AddMixed(&a.(*G1).G1Affine) + g.G1Affine.FromJacobian(j) +} + +func (g *G1) Mul(a driver.Zr) driver.G1 { + gc := &G1{} + gc.G1Affine.ScalarMultiplication(&g.G1Affine, &a.(*Zr).Int) + + return gc +} + +func (g *G1) Mul2(e driver.Zr, Q driver.G1, f driver.Zr) driver.G1 { + first := G1Jacs.Get() + defer G1Jacs.Put(first) + first = JointScalarMultiplication(first, &g.G1Affine, &Q.(*G1).G1Affine, &e.(*Zr).Int, &f.(*Zr).Int) + gc := &G1{} + gc.G1Affine.FromJacobian(first) + return gc +} + +func (g *G1) Mul2InPlace(e driver.Zr, Q driver.G1, f driver.Zr) { + first := G1Jacs.Get() + defer G1Jacs.Put(first) + first = JointScalarMultiplication(first, &g.G1Affine, &Q.(*G1).G1Affine, &e.(*Zr).Int, &f.(*Zr).Int) + g.G1Affine.FromJacobian(first) +} + +func (g *G1) Equals(a driver.G1) bool { + return g.G1Affine.Equal(&a.(*G1).G1Affine) +} + +func (g *G1) Bytes() []byte { + raw := g.G1Affine.RawBytes() + return raw[:] +} + +func (g *G1) Compressed() []byte { + raw := g.G1Affine.Bytes() + return raw[:] +} + +func (g *G1) Sub(a driver.G1) { + j, k := bls12381.G1Jac{}, bls12381.G1Jac{} + j.FromAffine(&g.G1Affine) + k.FromAffine(&a.(*G1).G1Affine) + j.SubAssign(&k) + g.G1Affine.FromJacobian(&j) +} + +func (g *G1) IsInfinity() bool { + return g.G1Affine.IsInfinity() +} + +func (g *G1) String() string { + rawstr := g.G1Affine.String() + m := g1StrRegexp.FindAllStringSubmatch(rawstr, -1) + return "(" + strings.TrimLeft(m[0][1], "0") + "," + strings.TrimLeft(m[0][2], "0") + ")" +} + +func (g *G1) Neg() { + g.G1Affine.Neg(&g.G1Affine) +} + +/*********************************************************************/ + +type G2 struct { + bls12381.G2Affine +} + +func (g *G2) Clone(a driver.G2) { + raw := a.(*G2).G2Affine.Bytes() + _, err := g.SetBytes(raw[:]) + if err != nil { + panic("could not copy point") + } +} + +func (e *G2) Copy() driver.G2 { + c := &G2{} + c.Set(&e.G2Affine) + return c +} + +func (g *G2) Mul(a driver.Zr) driver.G2 { + gc := &G2{} + gc.G2Affine.ScalarMultiplication(&g.G2Affine, &a.(*Zr).Int) + + return gc +} + +func (g *G2) Add(a driver.G2) { + j := bls12381.G2Jac{} + j.FromAffine(&g.G2Affine) + j.AddMixed((*bls12381.G2Affine)(&a.(*G2).G2Affine)) + g.G2Affine.FromJacobian(&j) +} + +func (g *G2) Sub(a driver.G2) { + j := bls12381.G2Jac{} + j.FromAffine(&g.G2Affine) + aJac := bls12381.G2Jac{} + aJac.FromAffine((*bls12381.G2Affine)(&a.(*G2).G2Affine)) + j.SubAssign(&aJac) + g.G2Affine.FromJacobian(&j) +} + +func (g *G2) Affine() { + // we're always affine +} + +func (g *G2) Bytes() []byte { + raw := g.G2Affine.RawBytes() + return raw[:] +} + +func (g *G2) Compressed() []byte { + raw := g.G2Affine.Bytes() + return raw[:] +} + +func (g *G2) String() string { + return g.G2Affine.String() +} + +func (g *G2) Equals(a driver.G2) bool { + return g.G2Affine.Equal(&a.(*G2).G2Affine) +} + +/*********************************************************************/ + +type Gt struct { + bls12381.GT +} + +func (g *Gt) Exp(x driver.Zr) driver.Gt { + c := bls12381.GT{} + return &Gt{*c.Exp(g.GT, &x.(*Zr).Int)} +} + +func (g *Gt) Equals(a driver.Gt) bool { + return g.GT.Equal(&a.(*Gt).GT) +} + +func (g *Gt) Inverse() { + g.GT.Inverse(&g.GT) +} + +func (g *Gt) Mul(a driver.Gt) { + g.GT.Mul(&g.GT, &a.(*Gt).GT) +} + +func (g *Gt) IsUnity() bool { + unity := bls12381.GT{} + unity.SetOne() + + return unity.Equal(&g.GT) +} + +func (g *Gt) ToString() string { + return g.GT.String() +} + +func (g *Gt) Bytes() []byte { + raw := g.GT.Bytes() + return raw[:] +} + +/*********************************************************************/ + +type Curve struct { + common.CurveBase +} + +func NewCurve() *Curve { + return &Curve{common.CurveBase{Modulus: *fr.Modulus()}} +} + +func (c *Curve) Pairing(p2 driver.G2, p1 driver.G1) driver.Gt { + t, err := bls12381.MillerLoop([]bls12381.G1Affine{p1.(*G1).G1Affine}, []bls12381.G2Affine{p2.(*G2).G2Affine}) + if err != nil { + panic(fmt.Sprintf("pairing failed [%s]", err.Error())) + } + + return &Gt{t} +} + +func (c *Curve) Pairing2(p2a, p2b driver.G2, p1a, p1b driver.G1) driver.Gt { + t, err := bls12381.MillerLoop([]bls12381.G1Affine{p1a.(*G1).G1Affine, p1b.(*G1).G1Affine}, []bls12381.G2Affine{p2a.(*G2).G2Affine, p2b.(*G2).G2Affine}) + if err != nil { + panic(fmt.Sprintf("pairing 2 failed [%s]", err.Error())) + } + + return &Gt{t} +} + +func (c *Curve) FExp(a driver.Gt) driver.Gt { + return &Gt{bls12381.FinalExponentiation(&a.(*Gt).GT)} +} + +func (c *Curve) GenG1() driver.G1 { + r := &G1{} + _, err := r.SetBytes(g1Bytes12_381[:]) + if err != nil { + panic("could not generate point") + } + + return r +} + +func (c *Curve) GenG2() driver.G2 { + r := &G2{} + _, err := r.SetBytes(g2Bytes12_381[:]) + if err != nil { + panic("could not generate point") + } + + return r +} + +func (c *Curve) GenGt() driver.Gt { + g1 := c.GenG1() + g2 := c.GenG2() + gengt := c.Pairing(g2, g1) + gengt = c.FExp(gengt) + return gengt +} + +func (c *Curve) CoordinateByteSize() int { + return bls12381.SizeOfG1AffineCompressed +} + +func (c *Curve) G1ByteSize() int { + return bls12381.SizeOfG1AffineUncompressed +} + +func (c *Curve) CompressedG1ByteSize() int { + return bls12381.SizeOfG1AffineCompressed +} + +func (c *Curve) G2ByteSize() int { + return bls12381.SizeOfG2AffineUncompressed +} + +func (c *Curve) CompressedG2ByteSize() int { + return bls12381.SizeOfG2AffineCompressed +} + +func (c *Curve) ScalarByteSize() int { + return common.ScalarByteSize +} + +func (c *Curve) NewG1() driver.G1 { + return &G1{} +} + +func (c *Curve) NewG2() driver.G2 { + return &G2{} +} + +func (c *Curve) NewG1FromBytes(b []byte) driver.G1 { + v := &G1{} + _, err := v.G1Affine.SetBytes(b) + if err != nil { + panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) + } + + return v +} + +func (c *Curve) NewG2FromBytes(b []byte) driver.G2 { + v := &G2{} + _, err := v.SetBytes(b) + if err != nil { + panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) + } + + return v +} + +func (c *Curve) NewG1FromCompressed(b []byte) driver.G1 { + v := &G1{} + _, err := v.SetBytes(b) + if err != nil { + panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) + } + + return v +} + +func (c *Curve) NewG2FromCompressed(b []byte) driver.G2 { + v := &G2{} + _, err := v.SetBytes(b) + if err != nil { + panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) + } + + return v +} + +func (c *Curve) NewGtFromBytes(b []byte) driver.Gt { + v := &Gt{} + err := v.SetBytes(b) + if err != nil { + panic(fmt.Sprintf("set bytes failed [%s]", err.Error())) + } + + return v +} + +func (c *Curve) ModNeg(a1, m driver.Zr) driver.Zr { + res := &Zr{Modulus: c.Modulus} + res.Int.Sub(&m.(*Zr).Int, &a1.(*Zr).Int) + res.Int.Mod(&res.Int, &m.(*Zr).Int) + + return res +} + +func (c *Curve) ModSub(a1, b1, m driver.Zr) driver.Zr { + a1Fr := frElements.Get() + defer frElements.Put(a1Fr) + a1Fr.SetBigInt(&a1.(*Zr).Int) + + a2Fr := frElements.Get() + defer frElements.Put(a2Fr) + a2Fr.SetBigInt(&b1.(*Zr).Int) + + a1Fr.Sub(a1Fr, a2Fr) + + res := &Zr{Modulus: c.Modulus} + a1Fr.BigInt(&res.Int) + return res +} + +func (c *Curve) GroupOrder() driver.Zr { + return &Zr{Int: c.Modulus, Modulus: c.Modulus} +} + +func (c *Curve) NewZrFromBytes(b []byte) driver.Zr { + res := &Zr{Modulus: c.Modulus} + res.Int.SetBytes(b) + return res +} + +func (c *Curve) NewZrFromInt64(i int64) driver.Zr { + return &Zr{Int: *big.NewInt(i), Modulus: c.Modulus} +} + +func (c *Curve) NewZrFromUint64(i uint64) driver.Zr { + return &Zr{Int: *new(big.Int).SetUint64(i), Modulus: c.Modulus} +} + +func (c *Curve) NewRandomZr(rng io.Reader) driver.Zr { + bi, err := rand.Int(rng, &c.Modulus) + if err != nil { + panic(err) + } + + return &Zr{Int: *bi, Modulus: c.Modulus} +} + +func (c *Curve) HashToZr(data []byte) driver.Zr { + digest := sha256.Sum256(data) + digestBig := new(big.Int).SetBytes(digest[:]) + digestBig.Mod(digestBig, &c.Modulus) + return &Zr{Int: *digestBig, Modulus: c.Modulus} +} + +func (p *Curve) Rand() (io.Reader, error) { + return rand.Reader, nil +} + +func (c *Curve) HashToG1(data []byte) driver.G1 { + g1, err := bls12381.HashToG1(data, []byte{}) + if err != nil { + panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) + } + + return &G1{g1} +} + +func (c *Curve) HashToG2(data []byte) driver.G2 { + g2, err := bls12381.HashToG2(data, []byte{}) + if err != nil { + panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) + } + + return &G2{g2} +} + +func (c *Curve) HashToG1WithDomain(data, domain []byte) driver.G1 { + g1, err := bls12381.HashToG1(data, domain) + if err != nil { + panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) + } + + return &G1{g1} +} + +func (c *Curve) HashToG2WithDomain(data, domain []byte) driver.G2 { + g2, err := bls12381.HashToG2(data, domain) + if err != nil { + panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) + } + + return &G2{g2} +} + +func (c *Curve) ModMul(a1, b1, m driver.Zr) driver.Zr { + a1Fr := frElements.Get() + defer frElements.Put(a1Fr) + a1Fr.SetBigInt(&a1.(*Zr).Int) + + a2Fr := frElements.Get() + defer frElements.Put(a2Fr) + a2Fr.SetBigInt(&b1.(*Zr).Int) + + a1Fr.Mul(a1Fr, a2Fr) + + res := &Zr{Modulus: c.Modulus} + a1Fr.BigInt(&res.Int) + return res +} + +func (c *Curve) ModAddMul(a1, b1 []driver.Zr, m driver.Zr) driver.Zr { + a1Fr := frElements.Get() + defer frElements.Put(a1Fr) + b1Fr := frElements.Get() + defer frElements.Put(b1Fr) + sum := frElements.Get() + defer frElements.Put(sum) + + sum.SetZero() + for i := 0; i < len(a1); i++ { + a1Fr.SetBigInt(&a1[i].(*Zr).Int) + b1Fr.SetBigInt(&b1[i].(*Zr).Int) + a1Fr.Mul(a1Fr, b1Fr) + sum.Add(sum, a1Fr) + } + + res := &Zr{Modulus: c.Modulus} + sum.BigInt(&res.Int) + return res +} + +func (c *Curve) ModAddMul2(a1 driver.Zr, c1 driver.Zr, b1 driver.Zr, c2 driver.Zr, m driver.Zr) driver.Zr { + aFr := frElements.Get() + defer frElements.Put(aFr) + cFr := frElements.Get() + defer frElements.Put(cFr) + + sum := frElements.Get() + defer frElements.Put(sum) + + sum.SetZero() + aFr.SetBigInt(&a1.(*Zr).Int) + cFr.SetBigInt(&c1.(*Zr).Int) + aFr.Mul(aFr, cFr) + sum.Add(sum, aFr) + + aFr.SetBigInt(&b1.(*Zr).Int) + cFr.SetBigInt(&c2.(*Zr).Int) + aFr.Mul(aFr, cFr) + sum.Add(sum, aFr) + + res := &Zr{Modulus: c.Modulus} + sum.BigInt(&res.Int) + return res +} + +func (c *Curve) ModAdd(a1, b1, m driver.Zr) driver.Zr { + a1Fr := frElements.Get() + defer frElements.Put(a1Fr) + a1Fr.SetBigInt(&a1.(*Zr).Int) + + a2Fr := frElements.Get() + defer frElements.Put(a2Fr) + a2Fr.SetBigInt(&b1.(*Zr).Int) + + a1Fr.Add(a1Fr, a2Fr) + + res := &Zr{Modulus: c.Modulus} + a1Fr.BigInt(&res.Int) + return res +} + +func (c *Curve) ModAdd2(a1, b1, c1, m driver.Zr) { + a1Fr := frElements.Get() + defer frElements.Put(a1Fr) + a1Fr.SetBigInt(&a1.(*Zr).Int) + + tmp := frElements.Get() + defer frElements.Put(tmp) + tmp.SetBigInt(&b1.(*Zr).Int) + + a1Fr.Add(a1Fr, tmp) + + tmp.SetBigInt(&c1.(*Zr).Int) + a1Fr.Add(a1Fr, tmp) + + a1Fr.BigInt(&a1.(*Zr).Int) +} + +type BBSCurve struct { + Curve +} + +func NewBBSCurve() *BBSCurve { + return &BBSCurve{*NewCurve()} +} + +func (c *BBSCurve) HashToG1(data []byte) driver.G1 { + hashFunc := func() hash.Hash { + // We pass a null key so error is impossible here. + h, _ := blake2b.New512(nil) //nolint:errcheck + return h + } + + g1, err := gurvy.HashToG1GenericBESwu(data, []byte{}, hashFunc) + if err != nil { + panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) + } + + return &G1{g1} +} + +func (c *BBSCurve) HashToG2(data []byte) driver.G2 { + g2, err := bls12381.HashToG2(data, []byte{}) + if err != nil { + panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) + } + + return &G2{g2} +} + +func (c *BBSCurve) HashToG1WithDomain(data, domain []byte) driver.G1 { + hashFunc := func() hash.Hash { + // We pass a null key so error is impossible here. + h, _ := blake2b.New512(nil) //nolint:errcheck + return h + } + + g1, err := gurvy.HashToG1GenericBESwu(data, domain, hashFunc) + if err != nil { + panic(fmt.Sprintf("HashToG1 failed [%s]", err.Error())) + } + + return &G1{g1} +} + +func (c *BBSCurve) HashToG2WithDomain(data, domain []byte) driver.G2 { + g2, err := bls12381.HashToG2(data, domain) + if err != nil { + panic(fmt.Sprintf("HashToG2 failed [%s]", err.Error())) + } + + return &G2{g2} +} + +// JointScalarMultiplication computes [s1]a1+[s2]a2 using Strauss-Shamir technique +// where a1 and a2 are affine points. +func JointScalarMultiplication(p *bls12381.G1Jac, a1, a2 *bls12381.G1Affine, s1, s2 *big.Int) *bls12381.G1Jac { + var res, p1, p2 bls12381.G1Jac + res.Set(&g1Infinity) + p1.FromAffine(a1) + p2.FromAffine(a2) + + var table [15]bls12381.G1Jac + + var k1, k2 big.Int + if s1.Sign() == -1 { + k1.Neg(s1) + table[0].Neg(&p1) + } else { + k1 = *s1 + table[0].Set(&p1) + } + if s2.Sign() == -1 { + k2.Neg(s2) + table[3].Neg(&p2) + } else { + k2 = *s2 + table[3].Set(&p2) + } + + // precompute table (2 bits sliding window) + table[1].Double(&table[0]) + table[2].Set(&table[1]).AddAssign(&table[0]) + table[4].Set(&table[3]).AddAssign(&table[0]) + table[5].Set(&table[3]).AddAssign(&table[1]) + table[6].Set(&table[3]).AddAssign(&table[2]) + table[7].Double(&table[3]) + table[8].Set(&table[7]).AddAssign(&table[0]) + table[9].Set(&table[7]).AddAssign(&table[1]) + table[10].Set(&table[7]).AddAssign(&table[2]) + table[11].Set(&table[7]).AddAssign(&table[3]) + table[12].Set(&table[11]).AddAssign(&table[0]) + table[13].Set(&table[11]).AddAssign(&table[1]) + table[14].Set(&table[11]).AddAssign(&table[2]) + + var s [2]fr.Element + s[0] = s[0].SetBigInt(&k1).Bits() + s[1] = s[1].SetBigInt(&k2).Bits() + + maxBit := k1.BitLen() + if k2.BitLen() > maxBit { + maxBit = k2.BitLen() + } + hiWordIndex := (maxBit - 1) / 64 + + for i := hiWordIndex; i >= 0; i-- { + mask := uint64(3) << 62 + for j := 0; j < 32; j++ { + res.Double(&res).Double(&res) + b1 := (s[0][i] & mask) >> (62 - 2*j) + b2 := (s[1][i] & mask) >> (62 - 2*j) + if b1|b2 != 0 { + s := (b2<<2 | b1) + res.AddAssign(&table[s-1]) + } + mask = mask >> 2 + } + } + + p.Set(&res) + return p + +} diff --git a/driver/gurvy/bls12381/frpool.go b/driver/gurvy/bls12381/frpool.go new file mode 100644 index 0000000..6153c6f --- /dev/null +++ b/driver/gurvy/bls12381/frpool.go @@ -0,0 +1,37 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package bls12381 + +import ( + "sync" + + "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" +) + +// frElements is a shared *bls12381.FrElement{} memory pool +var frElements frElementPool + +var _frElementPool = sync.Pool{ + New: func() interface{} { + return new(fr.Element) + }, +} + +type frElementPool struct{} + +func (frElementPool) Get() *fr.Element { + return _frElementPool.Get().(*fr.Element) +} + +func (frElementPool) Put(v *fr.Element) { + if v == nil { + panic("put called with nil value") + } + // reset v before putting it back + v.SetZero() + _frElementPool.Put(v) +} diff --git a/driver/gurvy/bls12381/g1pool.go b/driver/gurvy/bls12381/g1pool.go new file mode 100644 index 0000000..5fbf821 --- /dev/null +++ b/driver/gurvy/bls12381/g1pool.go @@ -0,0 +1,39 @@ +/* +Copyright IBM Corp. All Rights Reserved. + +SPDX-License-Identifier: Apache-2.0 +*/ + +package bls12381 + +import ( + "sync" + + bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381" +) + +// G1Jacs is a shared *bls12381.G1Jac{} memory pool +var G1Jacs g1JacPool + +var _g1JacPool = sync.Pool{ + New: func() interface{} { + return new(bls12381.G1Jac) + }, +} + +type g1JacPool struct{} + +func (g1JacPool) Get() *bls12381.G1Jac { + return _g1JacPool.Get().(*bls12381.G1Jac) +} + +func (g1JacPool) Put(v *bls12381.G1Jac) { + if v == nil { + panic("put called with nil value") + } + // reset v before putting it back + v.X.SetZero() + v.Y.SetZero() + v.Z.SetZero() + _g1JacPool.Put(v) +} diff --git a/driver/gurvy/bn254.go b/driver/gurvy/bn254.go index 55c476b..54c069c 100644 --- a/driver/gurvy/bn254.go +++ b/driver/gurvy/bn254.go @@ -59,6 +59,14 @@ func (g *bn254G1) Mul2(e driver.Zr, Q driver.G1, f driver.Zr) driver.G1 { return a } +func (g *bn254G1) Mul2InPlace(e driver.Zr, Q driver.G1, f driver.Zr) { + a := g.Mul(e) + b := Q.Mul(f) + a.Add(b) + + g.Set(&a.(*bn254G1).G1Affine) +} + func (g *bn254G1) Equals(a driver.G1) bool { return g.G1Affine.Equal(&a.(*bn254G1).G1Affine) } diff --git a/driver/kilic/bls12-381.go b/driver/kilic/bls12-381.go index b565e3f..e231cf4 100644 --- a/driver/kilic/bls12-381.go +++ b/driver/kilic/bls12-381.go @@ -56,6 +56,14 @@ func (g *bls12_381G1) Mul2(e driver.Zr, Q driver.G1, f driver.Zr) driver.G1 { return a } +func (g *bls12_381G1) Mul2InPlace(e driver.Zr, Q driver.G1, f driver.Zr) { + a := g.Mul(e) + b := Q.Mul(f) + a.Add(b) + + g.Set(&a.(*bls12_381G1).PointG1) +} + func (g *bls12_381G1) Equals(a driver.G1) bool { g1 := bls12381.NewG1() return g1.Equal(&a.(*bls12_381G1).PointG1, &g.PointG1) diff --git a/driver/math.go b/driver/math.go index a7ccff5..e6fc2e6 100644 --- a/driver/math.go +++ b/driver/math.go @@ -45,6 +45,8 @@ type Curve interface { HashToG2WithDomain(data, domain []byte) G2 NewRandomZr(rng io.Reader) Zr Rand() (io.Reader, error) + ModAddMul(driver []Zr, driver2 []Zr, zr Zr) Zr + ModAddMul2(a1 Zr, c1 Zr, b1 Zr, c2 Zr, m Zr) Zr } type Zr interface { @@ -60,6 +62,7 @@ type Zr interface { Clone(a Zr) String() string Neg() + InvModOrder() } type G1 interface { @@ -68,6 +71,7 @@ type G1 interface { Add(G1) Mul(Zr) G1 Mul2(e Zr, Q G1, f Zr) G1 + Mul2InPlace(e Zr, Q G1, f Zr) Equals(G1) bool Bytes() []byte Compressed() []byte diff --git a/go.mod b/go.mod index cb1215f..aac44f2 100644 --- a/go.mod +++ b/go.mod @@ -1,22 +1,24 @@ module github.com/IBM/mathlib -go 1.23.0 +go 1.24.0 + +toolchain go1.24.11 require ( - github.com/consensys/gnark-crypto v0.18.0 + github.com/consensys/gnark-crypto v0.19.2 github.com/hyperledger/fabric-amcl v0.0.0-20230602173724-9e02669dceb2 github.com/pkg/errors v0.9.1 - github.com/stretchr/testify v1.10.0 - golang.org/x/crypto v0.39.0 + github.com/stretchr/testify v1.11.1 + golang.org/x/crypto v0.47.0 ) require ( - github.com/bits-and-blooms/bitset v1.20.0 // indirect + github.com/bits-and-blooms/bitset v1.24.4 // indirect github.com/davecgh/go-spew v1.1.1 // indirect github.com/kilic/bls12-381 v0.1.0 github.com/kr/text v0.2.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rogpeppe/go-internal v1.11.0 // indirect - golang.org/x/sys v0.33.0 + github.com/rogpeppe/go-internal v1.14.1 // indirect + golang.org/x/sys v0.40.0 gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 1369512..23403af 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ -github.com/bits-and-blooms/bitset v1.20.0 h1:2F+rfL86jE2d/bmw7OhqUg2Sj/1rURkBn3MdfoPyRVU= -github.com/bits-and-blooms/bitset v1.20.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= -github.com/consensys/gnark-crypto v0.18.0 h1:vIye/FqI50VeAr0B3dx+YjeIvmc3LWz4yEfbWBpTUf0= -github.com/consensys/gnark-crypto v0.18.0/go.mod h1:L3mXGFTe1ZN+RSJ+CLjUt9x7PNdx8ubaYfDROyp2Z8c= +github.com/bits-and-blooms/bitset v1.24.4 h1:95H15Og1clikBrKr/DuzMXkQzECs1M6hhoGXLwLQOZE= +github.com/bits-and-blooms/bitset v1.24.4/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8= +github.com/consensys/gnark-crypto v0.19.2 h1:qrEAIXq3T4egxqiliFFoNrepkIWVEeIYwt3UL0fvS80= +github.com/consensys/gnark-crypto v0.19.2/go.mod h1:rT23F0XSZqE0mUA0+pRtnL56IbPxs6gp4CeRsBk4XS0= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -19,15 +19,15 @@ github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= -golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= +github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= +golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= golang.org/x/sys v0.0.0-20201101102859-da207088b7d1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= -golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= +golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= diff --git a/math.go b/math.go index 469713c..08eafbd 100644 --- a/math.go +++ b/math.go @@ -15,6 +15,7 @@ import ( "github.com/IBM/mathlib/driver" "github.com/IBM/mathlib/driver/amcl" "github.com/IBM/mathlib/driver/gurvy" + "github.com/IBM/mathlib/driver/gurvy/bls12381" "github.com/IBM/mathlib/driver/kilic" "github.com/pkg/errors" ) @@ -129,17 +130,17 @@ var Curves []*Curve = []*Curve{ curveID: BLS12_377_GURVY, }, { - c: gurvy.NewBls12_381(), - GenG1: NewG1((&gurvy.Bls12_381{}).GenG1(), BLS12_381_GURVY), - GenG2: NewG2((&gurvy.Bls12_381{}).GenG2(), BLS12_381_GURVY), - GenGt: NewGt((&gurvy.Bls12_381{}).GenGt(), BLS12_381_GURVY), - GroupOrder: NewZr(gurvy.NewBls12_381().GroupOrder(), BLS12_381_GURVY), - CoordByteSize: (&gurvy.Bls12_381{}).CoordinateByteSize(), - G1ByteSize: (&gurvy.Bls12_381{}).G1ByteSize(), - CompressedG1ByteSize: (&gurvy.Bls12_381{}).CompressedG1ByteSize(), - G2ByteSize: (&gurvy.Bls12_381{}).G2ByteSize(), - CompressedG2ByteSize: (&gurvy.Bls12_381{}).CompressedG2ByteSize(), - ScalarByteSize: (&gurvy.Bls12_381{}).ScalarByteSize(), + c: bls12381.NewCurve(), + GenG1: NewG1((&bls12381.Curve{}).GenG1(), BLS12_381_GURVY), + GenG2: NewG2((&bls12381.Curve{}).GenG2(), BLS12_381_GURVY), + GenGt: NewGt((&bls12381.Curve{}).GenGt(), BLS12_381_GURVY), + GroupOrder: NewZr(bls12381.NewCurve().GroupOrder(), BLS12_381_GURVY), + CoordByteSize: (&bls12381.Curve{}).CoordinateByteSize(), + G1ByteSize: (&bls12381.Curve{}).G1ByteSize(), + CompressedG1ByteSize: (&bls12381.Curve{}).CompressedG1ByteSize(), + G2ByteSize: (&bls12381.Curve{}).G2ByteSize(), + CompressedG2ByteSize: (&bls12381.Curve{}).CompressedG2ByteSize(), + ScalarByteSize: (&bls12381.Curve{}).ScalarByteSize(), curveID: BLS12_381_GURVY, }, { @@ -157,17 +158,17 @@ var Curves []*Curve = []*Curve{ curveID: BLS12_381_BBS, }, { - c: gurvy.NewBls12_381BBS(), - GenG1: NewG1(gurvy.NewBls12_381BBS().GenG1(), BLS12_381_BBS_GURVY), - GenG2: NewG2(gurvy.NewBls12_381BBS().GenG2(), BLS12_381_BBS_GURVY), - GenGt: NewGt(gurvy.NewBls12_381BBS().GenGt(), BLS12_381_BBS_GURVY), - GroupOrder: NewZr(gurvy.NewBls12_381().GroupOrder(), BLS12_381_BBS_GURVY), - CoordByteSize: gurvy.NewBls12_381BBS().CoordinateByteSize(), - G1ByteSize: gurvy.NewBls12_381BBS().G1ByteSize(), - CompressedG1ByteSize: gurvy.NewBls12_381BBS().CompressedG1ByteSize(), - G2ByteSize: gurvy.NewBls12_381BBS().G2ByteSize(), - CompressedG2ByteSize: gurvy.NewBls12_381BBS().CompressedG2ByteSize(), - ScalarByteSize: gurvy.NewBls12_381BBS().ScalarByteSize(), + c: bls12381.NewBBSCurve(), + GenG1: NewG1(bls12381.NewBBSCurve().GenG1(), BLS12_381_BBS_GURVY), + GenG2: NewG2(bls12381.NewBBSCurve().GenG2(), BLS12_381_BBS_GURVY), + GenGt: NewGt(bls12381.NewBBSCurve().GenGt(), BLS12_381_BBS_GURVY), + GroupOrder: NewZr(bls12381.NewCurve().GroupOrder(), BLS12_381_BBS_GURVY), + CoordByteSize: bls12381.NewBBSCurve().CoordinateByteSize(), + G1ByteSize: bls12381.NewBBSCurve().G1ByteSize(), + CompressedG1ByteSize: bls12381.NewBBSCurve().CompressedG1ByteSize(), + G2ByteSize: bls12381.NewBBSCurve().G2ByteSize(), + CompressedG2ByteSize: bls12381.NewBBSCurve().CompressedG2ByteSize(), + ScalarByteSize: bls12381.NewBBSCurve().ScalarByteSize(), curveID: BLS12_381_BBS_GURVY, }, } @@ -212,6 +213,10 @@ func (z *Zr) InvModP(a *Zr) { z.zr.InvModP(a.zr) } +func (z *Zr) InvModOrder() { + z.zr.InvModOrder() +} + func (z *Zr) Bytes() []byte { return z.zr.Bytes() } @@ -293,6 +298,10 @@ func (g *G1) Mul2(e *Zr, Q *G1, f *Zr) *G1 { return &G1{g1: g.g1.Mul2(e.zr, Q.g1, f.zr), curveID: g.curveID} } +func (g *G1) Mul2InPlace(e *Zr, Q *G1, f *Zr) { + g.g1.Mul2InPlace(e.zr, Q.g1, f.zr) +} + func (g *G1) Equals(a *G1) bool { return g.g1.Equals(a.g1) } @@ -604,3 +613,17 @@ func (c *Curve) ModMul(a1, b1, m *Zr) *Zr { func (c *Curve) ModNeg(a1, m *Zr) *Zr { return &Zr{zr: c.c.ModNeg(a1.zr, m.zr), curveID: c.curveID} } + +func (c *Curve) ModAddMul(a1, b1 []*Zr, m *Zr) *Zr { + a1Driver := make([]driver.Zr, len(a1)) + b1Driver := make([]driver.Zr, len(b1)) + for i := 0; i < len(a1); i++ { + a1Driver[i] = a1[i].zr + b1Driver[i] = b1[i].zr + } + return &Zr{zr: c.c.ModAddMul(a1Driver, b1Driver, m.zr), curveID: c.curveID} +} + +func (c *Curve) ModAddMul2(a, b, cc, d *Zr, m *Zr) *Zr { + return &Zr{zr: c.c.ModAddMul2(a.zr, b.zr, cc.zr, d.zr, m.zr), curveID: c.curveID} +} diff --git a/math_test.go b/math_test.go index f545de9..4826338 100644 --- a/math_test.go +++ b/math_test.go @@ -425,6 +425,18 @@ func runGtTest(t *testing.T, c *Curve) { assert.True(t, gengt.Equals(c.GenGt)) } +func runInvModOrderTest(t *testing.T, c *Curve) { + rng, err := c.Rand() + assert.NoError(t, err) + r := c.NewRandomZr(rng) + r1 := c.NewZrFromUint64(0) + r1.Clone(r) + + r.InvModP(c.GroupOrder) + r1.InvModOrder() + assert.True(t, r.Equals(r1)) +} + func runRndTest(t *testing.T, c *Curve) { rng, err := c.Rand() assert.NoError(t, err) @@ -540,6 +552,18 @@ func runModAddSubNegTest(t *testing.T, c *Curve) { apb := c.ModAdd(a, b, c.GroupOrder) bagain := c.ModSub(apb, a, c.GroupOrder) assert.True(t, bagain.Equals(b)) + + a2 := c.NewRandomZr(rng) + b2 := c.NewRandomZr(rng) + + v := c.ModAddMul2(a, b, a2, b2, c.GroupOrder) + atb := c.ModMul(a, b, c.GroupOrder) + a2tb2 := c.ModMul(a2, b2, c.GroupOrder) + v2 := c.ModAdd(atb, a2tb2, c.GroupOrder) + assert.True(t, v.Equals(v2)) + + v3 := c.ModAddMul([]*Zr{a, a2}, []*Zr{b, b2}, c.GroupOrder) + assert.True(t, v.Equals(v3)) } func runMulTest(t *testing.T, c *Curve) { @@ -662,6 +686,18 @@ func testModAdd(t *testing.T, c *Curve) { assert.True(t, g1.Equals(g2), fmt.Sprintf("failed with curve %T", c.c)) } +func testModAdd2(t *testing.T, c *Curve) { + i1 := c.NewZrFromInt(math.MaxInt64) + i2 := c.NewZrFromInt(math.MaxInt64) + g1 := c.GenG1.Mul2(i1, c.GenG1, i2) + + g2 := c.NewG1() + g2 = c.GenG1.Copy() + g2.Mul2InPlace(i1, c.GenG1, i2) + + assert.True(t, g1.Equals(g2), fmt.Sprintf("failed with curve %T", c.c)) +} + func testNotZeroAfterAdd(t *testing.T, c *Curve) { i1 := c.NewZrFromInt(math.MaxInt64) i2 := c.NewZrFromInt(math.MaxInt64) @@ -743,12 +779,14 @@ func TestCurves(t *testing.T) { for _, curve := range Curves { testNotZeroAfterAdd(t, curve) testModAdd(t, curve) + testModAdd2(t, curve) runZrTest(t, curve) runG1Test(t, curve) runG2Test(t, curve) runPairingTest(t, curve) runGtTest(t, curve) runRndTest(t, curve) + runInvModOrderTest(t, curve) runHashTest(t, curve) runToFroBytesTest(t, curve) runToFroCompressedTest(t, curve)