From ea1b7eb485488190660020103d4df701e8f2432e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A9ter=20Szil=C3=A1gyi?= Date: Tue, 13 Mar 2018 13:22:59 +0200 Subject: [PATCH] crypto/bn256: only use cloudflare for optimized architectures --- crypto/bn256/bn256.go | 488 +----------------- crypto/bn256/cloudflare/bn256.go | 481 +++++++++++++++++ crypto/bn256/{ => cloudflare}/bn256_test.go | 0 crypto/bn256/{ => cloudflare}/constants.go | 0 crypto/bn256/{ => cloudflare}/curve.go | 0 crypto/bn256/{ => cloudflare}/example_test.go | 0 crypto/bn256/{ => cloudflare}/gfp.go | 0 crypto/bn256/{ => cloudflare}/gfp12.go | 0 crypto/bn256/{ => cloudflare}/gfp2.go | 0 crypto/bn256/{ => cloudflare}/gfp6.go | 0 crypto/bn256/{ => cloudflare}/gfp_amd64.s | 0 crypto/bn256/{ => cloudflare}/gfp_arm64.s | 0 crypto/bn256/{ => cloudflare}/gfp_decl.go | 0 crypto/bn256/{ => cloudflare}/gfp_generic.go | 0 crypto/bn256/{ => cloudflare}/gfp_test.go | 0 crypto/bn256/{ => cloudflare}/main_test.go | 0 crypto/bn256/{ => cloudflare}/mul_amd64.h | 0 crypto/bn256/{ => cloudflare}/mul_arm64.h | 0 .../bn256/{ => cloudflare}/mul_bmi2_amd64.h | 0 crypto/bn256/{ => cloudflare}/optate.go | 0 crypto/bn256/{ => cloudflare}/twist.go | 0 21 files changed, 502 insertions(+), 467 deletions(-) create mode 100644 crypto/bn256/cloudflare/bn256.go rename crypto/bn256/{ => cloudflare}/bn256_test.go (100%) rename crypto/bn256/{ => cloudflare}/constants.go (100%) rename crypto/bn256/{ => cloudflare}/curve.go (100%) rename crypto/bn256/{ => cloudflare}/example_test.go (100%) rename crypto/bn256/{ => cloudflare}/gfp.go (100%) rename crypto/bn256/{ => cloudflare}/gfp12.go (100%) rename crypto/bn256/{ => cloudflare}/gfp2.go (100%) rename crypto/bn256/{ => cloudflare}/gfp6.go (100%) rename crypto/bn256/{ => cloudflare}/gfp_amd64.s (100%) rename crypto/bn256/{ => cloudflare}/gfp_arm64.s (100%) rename crypto/bn256/{ => cloudflare}/gfp_decl.go (100%) rename crypto/bn256/{ => cloudflare}/gfp_generic.go (100%) rename crypto/bn256/{ => cloudflare}/gfp_test.go (100%) rename crypto/bn256/{ => cloudflare}/main_test.go (100%) rename crypto/bn256/{ => cloudflare}/mul_amd64.h (100%) rename crypto/bn256/{ => cloudflare}/mul_arm64.h (100%) rename crypto/bn256/{ => cloudflare}/mul_bmi2_amd64.h (100%) rename crypto/bn256/{ => cloudflare}/optate.go (100%) rename crypto/bn256/{ => cloudflare}/twist.go (100%) diff --git a/crypto/bn256/bn256.go b/crypto/bn256/bn256.go index c6ea2d07e0..a8dfa8f67d 100644 --- a/crypto/bn256/bn256.go +++ b/crypto/bn256/bn256.go @@ -1,481 +1,35 @@ -// Package bn256 implements a particular bilinear group at the 128-bit security -// level. +// Copyright 2018 The go-ethereum Authors +// This file is part of the go-ethereum library. // -// Bilinear groups are the basis of many of the new cryptographic protocols that -// have been proposed over the past decade. They consist of a triplet of groups -// (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ -// is a generator of the respective group). That function is called a pairing -// function. +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. // -// This package specifically implements the Optimal Ate pairing over a 256-bit -// Barreto-Naehrig curve as described in -// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible -// with the implementation described in that paper. +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +// +build amd64 arm64 + +// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. package bn256 -import ( - "crypto/rand" - "errors" - "io" - "math/big" -) - -func randomK(r io.Reader) (k *big.Int, err error) { - for { - k, err = rand.Int(r, Order) - if k.Sign() > 0 || err != nil { - return - } - } -} +import "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" // G1 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 G1 struct { - p *curvePoint -} - -// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. -func RandomG1(r io.Reader) (*big.Int, *G1, error) { - k, err := randomK(r) - if err != nil { - return nil, nil, err - } - - return k, new(G1).ScalarBaseMult(k), nil -} - -func (g *G1) String() string { - return "bn256.G1" + g.p.String() -} - -// ScalarBaseMult sets e to g*k where g is the generator of the group and then -// returns e. -func (e *G1) ScalarBaseMult(k *big.Int) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Mul(curveGen, k) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Mul(a.p, k) - return e -} - -// Add sets e to a+b and then returns e. -func (e *G1) Add(a, b *G1) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Add(a.p, b.p) - return e -} - -// Neg sets e to -a and then returns e. -func (e *G1) Neg(a *G1) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Neg(a.p) - return e -} - -// Set sets e to a and then returns e. -func (e *G1) Set(a *G1) *G1 { - if e.p == nil { - e.p = &curvePoint{} - } - e.p.Set(a.p) - return e -} - -// Marshal converts e to a byte slice. -func (e *G1) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - e.p.MakeAffine() - ret := make([]byte, numBytes*2) - if e.p.IsInfinity() { - return ret - } - temp := &gfP{} - - montDecode(temp, &e.p.x) - temp.Marshal(ret) - montDecode(temp, &e.p.y) - temp.Marshal(ret[numBytes:]) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *G1) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - if len(m) < 2*numBytes { - return nil, errors.New("bn256: not enough data") - } - // Unmarshal the points and check their caps - if e.p == nil { - e.p = &curvePoint{} - } else { - e.p.x, e.p.y = gfP{0}, gfP{0} - } - var err error - if err = e.p.x.Unmarshal(m); err != nil { - return nil, err - } - if err = e.p.y.Unmarshal(m[numBytes:]); err != nil { - return nil, err - } - // Encode into Montgomery form and ensure it's on the curve - montEncode(&e.p.x, &e.p.x) - montEncode(&e.p.y, &e.p.y) - - zero := gfP{0} - if e.p.x == zero && e.p.y == zero { - // This is the point at infinity. - e.p.y = *newGFp(1) - e.p.z = gfP{0} - e.p.t = gfP{0} - } else { - e.p.z = *newGFp(1) - e.p.t = *newGFp(1) - - if !e.p.IsOnCurve() { - return nil, errors.New("bn256: malformed point") - } - } - return m[2*numBytes:], nil -} +type G1 = bn256.G1 // 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 -} - -// 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 "bn256.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 - - if e.p == nil { - e.p = &twistPoint{} - } - - e.p.MakeAffine() - ret := make([]byte, numBytes*4) - if e.p.IsInfinity() { - return ret - } - temp := &gfP{} - - montDecode(temp, &e.p.x.x) - temp.Marshal(ret) - montDecode(temp, &e.p.x.y) - temp.Marshal(ret[numBytes:]) - montDecode(temp, &e.p.y.x) - temp.Marshal(ret[2*numBytes:]) - montDecode(temp, &e.p.y.y) - temp.Marshal(ret[3*numBytes:]) - - return ret -} - -// 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("bn256: 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("bn256: malformed point") - } - } - return m[4*numBytes:], nil -} - -// GT 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 GT struct { - p *gfP12 -} - -// Pair calculates an Optimal Ate pairing. -func Pair(g1 *G1, g2 *G2) *GT { - return >{optimalAte(g2.p, g1.p)} -} +type G2 = bn256.G2 // PairingCheck calculates the Optimal Ate pairing for a set of points. func PairingCheck(a []*G1, b []*G2) bool { - acc := new(gfP12) - acc.SetOne() - - for i := 0; i < len(a); i++ { - if a[i].p.IsInfinity() || b[i].p.IsInfinity() { - continue - } - acc.Mul(acc, miller(b[i].p, a[i].p)) - } - return finalExponentiation(acc).IsOne() -} - -// Miller applies Miller's algorithm, which is a bilinear function from the -// source groups to F_p^12. Miller(g1, g2).Finalize() is equivalent to Pair(g1, -// g2). -func Miller(g1 *G1, g2 *G2) *GT { - return >{miller(g2.p, g1.p)} -} - -func (g *GT) String() string { - return "bn256.GT" + g.p.String() -} - -// ScalarMult sets e to a*k and then returns e. -func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Exp(a.p, k) - return e -} - -// Add sets e to a+b and then returns e. -func (e *GT) Add(a, b *GT) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Mul(a.p, b.p) - return e -} - -// Neg sets e to -a and then returns e. -func (e *GT) Neg(a *GT) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Conjugate(a.p) - return e -} - -// Set sets e to a and then returns e. -func (e *GT) Set(a *GT) *GT { - if e.p == nil { - e.p = &gfP12{} - } - e.p.Set(a.p) - return e -} - -// Finalize is a linear function from F_p^12 to GT. -func (e *GT) Finalize() *GT { - ret := finalExponentiation(e.p) - e.p.Set(ret) - return e -} - -// Marshal converts e into a byte slice. -func (e *GT) Marshal() []byte { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - ret := make([]byte, numBytes*12) - temp := &gfP{} - - montDecode(temp, &e.p.x.x.x) - temp.Marshal(ret) - montDecode(temp, &e.p.x.x.y) - temp.Marshal(ret[numBytes:]) - montDecode(temp, &e.p.x.y.x) - temp.Marshal(ret[2*numBytes:]) - montDecode(temp, &e.p.x.y.y) - temp.Marshal(ret[3*numBytes:]) - montDecode(temp, &e.p.x.z.x) - temp.Marshal(ret[4*numBytes:]) - montDecode(temp, &e.p.x.z.y) - temp.Marshal(ret[5*numBytes:]) - montDecode(temp, &e.p.y.x.x) - temp.Marshal(ret[6*numBytes:]) - montDecode(temp, &e.p.y.x.y) - temp.Marshal(ret[7*numBytes:]) - montDecode(temp, &e.p.y.y.x) - temp.Marshal(ret[8*numBytes:]) - montDecode(temp, &e.p.y.y.y) - temp.Marshal(ret[9*numBytes:]) - montDecode(temp, &e.p.y.z.x) - temp.Marshal(ret[10*numBytes:]) - montDecode(temp, &e.p.y.z.y) - temp.Marshal(ret[11*numBytes:]) - - return ret -} - -// Unmarshal sets e to the result of converting the output of Marshal back into -// a group element and then returns e. -func (e *GT) Unmarshal(m []byte) ([]byte, error) { - // Each value is a 256-bit number. - const numBytes = 256 / 8 - - if len(m) < 12*numBytes { - return nil, errors.New("bn256: not enough data") - } - - if e.p == nil { - e.p = &gfP12{} - } - - var err error - if err = e.p.x.x.x.Unmarshal(m); err != nil { - return nil, err - } - if err = e.p.x.x.y.Unmarshal(m[numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.y.x.Unmarshal(m[2*numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.y.y.Unmarshal(m[3*numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.z.x.Unmarshal(m[4*numBytes:]); err != nil { - return nil, err - } - if err = e.p.x.z.y.Unmarshal(m[5*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.x.x.Unmarshal(m[6*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.x.y.Unmarshal(m[7*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.y.x.Unmarshal(m[8*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.y.y.Unmarshal(m[9*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.z.x.Unmarshal(m[10*numBytes:]); err != nil { - return nil, err - } - if err = e.p.y.z.y.Unmarshal(m[11*numBytes:]); err != nil { - return nil, err - } - montEncode(&e.p.x.x.x, &e.p.x.x.x) - montEncode(&e.p.x.x.y, &e.p.x.x.y) - montEncode(&e.p.x.y.x, &e.p.x.y.x) - montEncode(&e.p.x.y.y, &e.p.x.y.y) - montEncode(&e.p.x.z.x, &e.p.x.z.x) - montEncode(&e.p.x.z.y, &e.p.x.z.y) - montEncode(&e.p.y.x.x, &e.p.y.x.x) - montEncode(&e.p.y.x.y, &e.p.y.x.y) - montEncode(&e.p.y.y.x, &e.p.y.y.x) - montEncode(&e.p.y.y.y, &e.p.y.y.y) - montEncode(&e.p.y.z.x, &e.p.y.z.x) - montEncode(&e.p.y.z.y, &e.p.y.z.y) - - return m[12*numBytes:], nil + return bn256.PairingCheck(a, b) } diff --git a/crypto/bn256/cloudflare/bn256.go b/crypto/bn256/cloudflare/bn256.go new file mode 100644 index 0000000000..c6ea2d07e0 --- /dev/null +++ b/crypto/bn256/cloudflare/bn256.go @@ -0,0 +1,481 @@ +// Package bn256 implements a particular bilinear group at the 128-bit security +// level. +// +// Bilinear groups are the basis of many of the new cryptographic protocols that +// have been proposed over the past decade. They consist of a triplet of groups +// (G₁, G₂ and GT) such that there exists a function e(g₁ˣ,g₂ʸ)=gTˣʸ (where gₓ +// is a generator of the respective group). That function is called a pairing +// function. +// +// This package specifically implements the Optimal Ate pairing over a 256-bit +// Barreto-Naehrig curve as described in +// http://cryptojedi.org/papers/dclxvi-20100714.pdf. Its output is compatible +// with the implementation described in that paper. +package bn256 + +import ( + "crypto/rand" + "errors" + "io" + "math/big" +) + +func randomK(r io.Reader) (k *big.Int, err error) { + for { + k, err = rand.Int(r, Order) + if k.Sign() > 0 || err != nil { + return + } + } +} + +// G1 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 G1 struct { + p *curvePoint +} + +// RandomG1 returns x and g₁ˣ where x is a random, non-zero number read from r. +func RandomG1(r io.Reader) (*big.Int, *G1, error) { + k, err := randomK(r) + if err != nil { + return nil, nil, err + } + + return k, new(G1).ScalarBaseMult(k), nil +} + +func (g *G1) String() string { + return "bn256.G1" + g.p.String() +} + +// ScalarBaseMult sets e to g*k where g is the generator of the group and then +// returns e. +func (e *G1) ScalarBaseMult(k *big.Int) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Mul(curveGen, k) + return e +} + +// ScalarMult sets e to a*k and then returns e. +func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Mul(a.p, k) + return e +} + +// Add sets e to a+b and then returns e. +func (e *G1) Add(a, b *G1) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Add(a.p, b.p) + return e +} + +// Neg sets e to -a and then returns e. +func (e *G1) Neg(a *G1) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Neg(a.p) + return e +} + +// Set sets e to a and then returns e. +func (e *G1) Set(a *G1) *G1 { + if e.p == nil { + e.p = &curvePoint{} + } + e.p.Set(a.p) + return e +} + +// Marshal converts e to a byte slice. +func (e *G1) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + e.p.MakeAffine() + ret := make([]byte, numBytes*2) + if e.p.IsInfinity() { + return ret + } + temp := &gfP{} + + montDecode(temp, &e.p.x) + temp.Marshal(ret) + montDecode(temp, &e.p.y) + temp.Marshal(ret[numBytes:]) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *G1) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + if len(m) < 2*numBytes { + return nil, errors.New("bn256: not enough data") + } + // Unmarshal the points and check their caps + if e.p == nil { + e.p = &curvePoint{} + } else { + e.p.x, e.p.y = gfP{0}, gfP{0} + } + var err error + if err = e.p.x.Unmarshal(m); err != nil { + return nil, err + } + if err = e.p.y.Unmarshal(m[numBytes:]); err != nil { + return nil, err + } + // Encode into Montgomery form and ensure it's on the curve + montEncode(&e.p.x, &e.p.x) + montEncode(&e.p.y, &e.p.y) + + zero := gfP{0} + if e.p.x == zero && e.p.y == zero { + // This is the point at infinity. + e.p.y = *newGFp(1) + e.p.z = gfP{0} + e.p.t = gfP{0} + } else { + e.p.z = *newGFp(1) + e.p.t = *newGFp(1) + + if !e.p.IsOnCurve() { + return nil, errors.New("bn256: malformed point") + } + } + return m[2*numBytes:], nil +} + +// 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 +} + +// 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 "bn256.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 + + if e.p == nil { + e.p = &twistPoint{} + } + + e.p.MakeAffine() + ret := make([]byte, numBytes*4) + if e.p.IsInfinity() { + return ret + } + temp := &gfP{} + + montDecode(temp, &e.p.x.x) + temp.Marshal(ret) + montDecode(temp, &e.p.x.y) + temp.Marshal(ret[numBytes:]) + montDecode(temp, &e.p.y.x) + temp.Marshal(ret[2*numBytes:]) + montDecode(temp, &e.p.y.y) + temp.Marshal(ret[3*numBytes:]) + + return ret +} + +// 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("bn256: 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("bn256: malformed point") + } + } + return m[4*numBytes:], nil +} + +// GT 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 GT struct { + p *gfP12 +} + +// Pair calculates an Optimal Ate pairing. +func Pair(g1 *G1, g2 *G2) *GT { + return >{optimalAte(g2.p, g1.p)} +} + +// PairingCheck calculates the Optimal Ate pairing for a set of points. +func PairingCheck(a []*G1, b []*G2) bool { + acc := new(gfP12) + acc.SetOne() + + for i := 0; i < len(a); i++ { + if a[i].p.IsInfinity() || b[i].p.IsInfinity() { + continue + } + acc.Mul(acc, miller(b[i].p, a[i].p)) + } + return finalExponentiation(acc).IsOne() +} + +// Miller applies Miller's algorithm, which is a bilinear function from the +// source groups to F_p^12. Miller(g1, g2).Finalize() is equivalent to Pair(g1, +// g2). +func Miller(g1 *G1, g2 *G2) *GT { + return >{miller(g2.p, g1.p)} +} + +func (g *GT) String() string { + return "bn256.GT" + g.p.String() +} + +// ScalarMult sets e to a*k and then returns e. +func (e *GT) ScalarMult(a *GT, k *big.Int) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Exp(a.p, k) + return e +} + +// Add sets e to a+b and then returns e. +func (e *GT) Add(a, b *GT) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Mul(a.p, b.p) + return e +} + +// Neg sets e to -a and then returns e. +func (e *GT) Neg(a *GT) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Conjugate(a.p) + return e +} + +// Set sets e to a and then returns e. +func (e *GT) Set(a *GT) *GT { + if e.p == nil { + e.p = &gfP12{} + } + e.p.Set(a.p) + return e +} + +// Finalize is a linear function from F_p^12 to GT. +func (e *GT) Finalize() *GT { + ret := finalExponentiation(e.p) + e.p.Set(ret) + return e +} + +// Marshal converts e into a byte slice. +func (e *GT) Marshal() []byte { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + ret := make([]byte, numBytes*12) + temp := &gfP{} + + montDecode(temp, &e.p.x.x.x) + temp.Marshal(ret) + montDecode(temp, &e.p.x.x.y) + temp.Marshal(ret[numBytes:]) + montDecode(temp, &e.p.x.y.x) + temp.Marshal(ret[2*numBytes:]) + montDecode(temp, &e.p.x.y.y) + temp.Marshal(ret[3*numBytes:]) + montDecode(temp, &e.p.x.z.x) + temp.Marshal(ret[4*numBytes:]) + montDecode(temp, &e.p.x.z.y) + temp.Marshal(ret[5*numBytes:]) + montDecode(temp, &e.p.y.x.x) + temp.Marshal(ret[6*numBytes:]) + montDecode(temp, &e.p.y.x.y) + temp.Marshal(ret[7*numBytes:]) + montDecode(temp, &e.p.y.y.x) + temp.Marshal(ret[8*numBytes:]) + montDecode(temp, &e.p.y.y.y) + temp.Marshal(ret[9*numBytes:]) + montDecode(temp, &e.p.y.z.x) + temp.Marshal(ret[10*numBytes:]) + montDecode(temp, &e.p.y.z.y) + temp.Marshal(ret[11*numBytes:]) + + return ret +} + +// Unmarshal sets e to the result of converting the output of Marshal back into +// a group element and then returns e. +func (e *GT) Unmarshal(m []byte) ([]byte, error) { + // Each value is a 256-bit number. + const numBytes = 256 / 8 + + if len(m) < 12*numBytes { + return nil, errors.New("bn256: not enough data") + } + + if e.p == nil { + e.p = &gfP12{} + } + + var err error + if err = e.p.x.x.x.Unmarshal(m); err != nil { + return nil, err + } + if err = e.p.x.x.y.Unmarshal(m[numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.y.x.Unmarshal(m[2*numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.y.y.Unmarshal(m[3*numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.z.x.Unmarshal(m[4*numBytes:]); err != nil { + return nil, err + } + if err = e.p.x.z.y.Unmarshal(m[5*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.x.x.Unmarshal(m[6*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.x.y.Unmarshal(m[7*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.y.x.Unmarshal(m[8*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.y.y.Unmarshal(m[9*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.z.x.Unmarshal(m[10*numBytes:]); err != nil { + return nil, err + } + if err = e.p.y.z.y.Unmarshal(m[11*numBytes:]); err != nil { + return nil, err + } + montEncode(&e.p.x.x.x, &e.p.x.x.x) + montEncode(&e.p.x.x.y, &e.p.x.x.y) + montEncode(&e.p.x.y.x, &e.p.x.y.x) + montEncode(&e.p.x.y.y, &e.p.x.y.y) + montEncode(&e.p.x.z.x, &e.p.x.z.x) + montEncode(&e.p.x.z.y, &e.p.x.z.y) + montEncode(&e.p.y.x.x, &e.p.y.x.x) + montEncode(&e.p.y.x.y, &e.p.y.x.y) + montEncode(&e.p.y.y.x, &e.p.y.y.x) + montEncode(&e.p.y.y.y, &e.p.y.y.y) + montEncode(&e.p.y.z.x, &e.p.y.z.x) + montEncode(&e.p.y.z.y, &e.p.y.z.y) + + return m[12*numBytes:], nil +} diff --git a/crypto/bn256/bn256_test.go b/crypto/bn256/cloudflare/bn256_test.go similarity index 100% rename from crypto/bn256/bn256_test.go rename to crypto/bn256/cloudflare/bn256_test.go diff --git a/crypto/bn256/constants.go b/crypto/bn256/cloudflare/constants.go similarity index 100% rename from crypto/bn256/constants.go rename to crypto/bn256/cloudflare/constants.go diff --git a/crypto/bn256/curve.go b/crypto/bn256/cloudflare/curve.go similarity index 100% rename from crypto/bn256/curve.go rename to crypto/bn256/cloudflare/curve.go diff --git a/crypto/bn256/example_test.go b/crypto/bn256/cloudflare/example_test.go similarity index 100% rename from crypto/bn256/example_test.go rename to crypto/bn256/cloudflare/example_test.go diff --git a/crypto/bn256/gfp.go b/crypto/bn256/cloudflare/gfp.go similarity index 100% rename from crypto/bn256/gfp.go rename to crypto/bn256/cloudflare/gfp.go diff --git a/crypto/bn256/gfp12.go b/crypto/bn256/cloudflare/gfp12.go similarity index 100% rename from crypto/bn256/gfp12.go rename to crypto/bn256/cloudflare/gfp12.go diff --git a/crypto/bn256/gfp2.go b/crypto/bn256/cloudflare/gfp2.go similarity index 100% rename from crypto/bn256/gfp2.go rename to crypto/bn256/cloudflare/gfp2.go diff --git a/crypto/bn256/gfp6.go b/crypto/bn256/cloudflare/gfp6.go similarity index 100% rename from crypto/bn256/gfp6.go rename to crypto/bn256/cloudflare/gfp6.go diff --git a/crypto/bn256/gfp_amd64.s b/crypto/bn256/cloudflare/gfp_amd64.s similarity index 100% rename from crypto/bn256/gfp_amd64.s rename to crypto/bn256/cloudflare/gfp_amd64.s diff --git a/crypto/bn256/gfp_arm64.s b/crypto/bn256/cloudflare/gfp_arm64.s similarity index 100% rename from crypto/bn256/gfp_arm64.s rename to crypto/bn256/cloudflare/gfp_arm64.s diff --git a/crypto/bn256/gfp_decl.go b/crypto/bn256/cloudflare/gfp_decl.go similarity index 100% rename from crypto/bn256/gfp_decl.go rename to crypto/bn256/cloudflare/gfp_decl.go diff --git a/crypto/bn256/gfp_generic.go b/crypto/bn256/cloudflare/gfp_generic.go similarity index 100% rename from crypto/bn256/gfp_generic.go rename to crypto/bn256/cloudflare/gfp_generic.go diff --git a/crypto/bn256/gfp_test.go b/crypto/bn256/cloudflare/gfp_test.go similarity index 100% rename from crypto/bn256/gfp_test.go rename to crypto/bn256/cloudflare/gfp_test.go diff --git a/crypto/bn256/main_test.go b/crypto/bn256/cloudflare/main_test.go similarity index 100% rename from crypto/bn256/main_test.go rename to crypto/bn256/cloudflare/main_test.go diff --git a/crypto/bn256/mul_amd64.h b/crypto/bn256/cloudflare/mul_amd64.h similarity index 100% rename from crypto/bn256/mul_amd64.h rename to crypto/bn256/cloudflare/mul_amd64.h diff --git a/crypto/bn256/mul_arm64.h b/crypto/bn256/cloudflare/mul_arm64.h similarity index 100% rename from crypto/bn256/mul_arm64.h rename to crypto/bn256/cloudflare/mul_arm64.h diff --git a/crypto/bn256/mul_bmi2_amd64.h b/crypto/bn256/cloudflare/mul_bmi2_amd64.h similarity index 100% rename from crypto/bn256/mul_bmi2_amd64.h rename to crypto/bn256/cloudflare/mul_bmi2_amd64.h diff --git a/crypto/bn256/optate.go b/crypto/bn256/cloudflare/optate.go similarity index 100% rename from crypto/bn256/optate.go rename to crypto/bn256/cloudflare/optate.go diff --git a/crypto/bn256/twist.go b/crypto/bn256/cloudflare/twist.go similarity index 100% rename from crypto/bn256/twist.go rename to crypto/bn256/cloudflare/twist.go