mirror of https://github.com/ethereum/go-ethereum
Merge pull request #14336 from obscuren/metropolis-preparation
consensus, core/*, params: metropolis preparation refactorpull/14512/head
commit
261b3e2351
@ -0,0 +1 @@ |
||||
package vm |
@ -0,0 +1,428 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// 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" |
||||
"io" |
||||
"math/big" |
||||
) |
||||
|
||||
// BUG(agl): this implementation is not constant time.
|
||||
// TODO(agl): keep GF(p²) elements in Mongomery form.
|
||||
|
||||
// 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) { |
||||
var k *big.Int |
||||
var err error |
||||
|
||||
for { |
||||
k, err = rand.Int(r, Order) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
if k.Sign() > 0 { |
||||
break |
||||
} |
||||
} |
||||
|
||||
return k, new(G1).ScalarBaseMult(k), nil |
||||
} |
||||
|
||||
func (g *G1) String() string { |
||||
return "bn256.G1" + g.p.String() |
||||
} |
||||
|
||||
// CurvePoints returns p's curve points in big integer
|
||||
func (e *G1) CurvePoints() (*big.Int, *big.Int, *big.Int, *big.Int) { |
||||
return e.p.x, e.p.y, e.p.z, e.p.t |
||||
} |
||||
|
||||
// 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 = newCurvePoint(nil) |
||||
} |
||||
e.p.Mul(curveGen, k, new(bnPool)) |
||||
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 = newCurvePoint(nil) |
||||
} |
||||
e.p.Mul(a.p, k, new(bnPool)) |
||||
return e |
||||
} |
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
// BUG(agl): this function is not complete: a==b fails.
|
||||
func (e *G1) Add(a, b *G1) *G1 { |
||||
if e.p == nil { |
||||
e.p = newCurvePoint(nil) |
||||
} |
||||
e.p.Add(a.p, b.p, new(bnPool)) |
||||
return e |
||||
} |
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *G1) Neg(a *G1) *G1 { |
||||
if e.p == nil { |
||||
e.p = newCurvePoint(nil) |
||||
} |
||||
e.p.Negative(a.p) |
||||
return e |
||||
} |
||||
|
||||
// Marshal converts n to a byte slice.
|
||||
func (n *G1) Marshal() []byte { |
||||
n.p.MakeAffine(nil) |
||||
|
||||
xBytes := new(big.Int).Mod(n.p.x, P).Bytes() |
||||
yBytes := new(big.Int).Mod(n.p.y, P).Bytes() |
||||
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8 |
||||
|
||||
ret := make([]byte, numBytes*2) |
||||
copy(ret[1*numBytes-len(xBytes):], xBytes) |
||||
copy(ret[2*numBytes-len(yBytes):], yBytes) |
||||
|
||||
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) (*G1, bool) { |
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8 |
||||
|
||||
if len(m) != 2*numBytes { |
||||
return nil, false |
||||
} |
||||
|
||||
if e.p == nil { |
||||
e.p = newCurvePoint(nil) |
||||
} |
||||
|
||||
e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) |
||||
e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) |
||||
|
||||
if e.p.x.Sign() == 0 && e.p.y.Sign() == 0 { |
||||
// This is the point at infinity.
|
||||
e.p.y.SetInt64(1) |
||||
e.p.z.SetInt64(0) |
||||
e.p.t.SetInt64(0) |
||||
} else { |
||||
e.p.z.SetInt64(1) |
||||
e.p.t.SetInt64(1) |
||||
|
||||
if !e.p.IsOnCurve() { |
||||
return nil, false |
||||
} |
||||
} |
||||
|
||||
return e, true |
||||
} |
||||
|
||||
// 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 |
||||
} |
||||
|
||||
// RandomG1 returns x and g₂ˣ where x is a random, non-zero number read from r.
|
||||
func RandomG2(r io.Reader) (*big.Int, *G2, error) { |
||||
var k *big.Int |
||||
var err error |
||||
|
||||
for { |
||||
k, err = rand.Int(r, Order) |
||||
if err != nil { |
||||
return nil, nil, err |
||||
} |
||||
if k.Sign() > 0 { |
||||
break |
||||
} |
||||
} |
||||
|
||||
return k, new(G2).ScalarBaseMult(k), nil |
||||
} |
||||
|
||||
func (g *G2) String() string { |
||||
return "bn256.G2" + g.p.String() |
||||
} |
||||
|
||||
// CurvePoints returns the curve points of p which includes the real
|
||||
// and imaginary parts of the curve point.
|
||||
func (e *G2) CurvePoints() (*gfP2, *gfP2, *gfP2, *gfP2) { |
||||
return e.p.x, e.p.y, e.p.z, e.p.t |
||||
} |
||||
|
||||
// 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 = newTwistPoint(nil) |
||||
} |
||||
e.p.Mul(twistGen, k, new(bnPool)) |
||||
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 = newTwistPoint(nil) |
||||
} |
||||
e.p.Mul(a.p, k, new(bnPool)) |
||||
return e |
||||
} |
||||
|
||||
// Add sets e to a+b and then returns e.
|
||||
// BUG(agl): this function is not complete: a==b fails.
|
||||
func (e *G2) Add(a, b *G2) *G2 { |
||||
if e.p == nil { |
||||
e.p = newTwistPoint(nil) |
||||
} |
||||
e.p.Add(a.p, b.p, new(bnPool)) |
||||
return e |
||||
} |
||||
|
||||
// Marshal converts n into a byte slice.
|
||||
func (n *G2) Marshal() []byte { |
||||
n.p.MakeAffine(nil) |
||||
|
||||
xxBytes := new(big.Int).Mod(n.p.x.x, P).Bytes() |
||||
xyBytes := new(big.Int).Mod(n.p.x.y, P).Bytes() |
||||
yxBytes := new(big.Int).Mod(n.p.y.x, P).Bytes() |
||||
yyBytes := new(big.Int).Mod(n.p.y.y, P).Bytes() |
||||
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8 |
||||
|
||||
ret := make([]byte, numBytes*4) |
||||
copy(ret[1*numBytes-len(xxBytes):], xxBytes) |
||||
copy(ret[2*numBytes-len(xyBytes):], xyBytes) |
||||
copy(ret[3*numBytes-len(yxBytes):], yxBytes) |
||||
copy(ret[4*numBytes-len(yyBytes):], yyBytes) |
||||
|
||||
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) (*G2, bool) { |
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8 |
||||
|
||||
if len(m) != 4*numBytes { |
||||
return nil, false |
||||
} |
||||
|
||||
if e.p == nil { |
||||
e.p = newTwistPoint(nil) |
||||
} |
||||
|
||||
e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) |
||||
e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) |
||||
e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) |
||||
e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) |
||||
|
||||
if e.p.x.x.Sign() == 0 && |
||||
e.p.x.y.Sign() == 0 && |
||||
e.p.y.x.Sign() == 0 && |
||||
e.p.y.y.Sign() == 0 { |
||||
// 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, false |
||||
} |
||||
} |
||||
|
||||
return e, true |
||||
} |
||||
|
||||
// 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 |
||||
} |
||||
|
||||
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 = newGFp12(nil) |
||||
} |
||||
e.p.Exp(a.p, k, new(bnPool)) |
||||
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 = newGFp12(nil) |
||||
} |
||||
e.p.Mul(a.p, b.p, new(bnPool)) |
||||
return e |
||||
} |
||||
|
||||
// Neg sets e to -a and then returns e.
|
||||
func (e *GT) Neg(a *GT) *GT { |
||||
if e.p == nil { |
||||
e.p = newGFp12(nil) |
||||
} |
||||
e.p.Invert(a.p, new(bnPool)) |
||||
return e |
||||
} |
||||
|
||||
// Marshal converts n into a byte slice.
|
||||
func (n *GT) Marshal() []byte { |
||||
n.p.Minimal() |
||||
|
||||
xxxBytes := n.p.x.x.x.Bytes() |
||||
xxyBytes := n.p.x.x.y.Bytes() |
||||
xyxBytes := n.p.x.y.x.Bytes() |
||||
xyyBytes := n.p.x.y.y.Bytes() |
||||
xzxBytes := n.p.x.z.x.Bytes() |
||||
xzyBytes := n.p.x.z.y.Bytes() |
||||
yxxBytes := n.p.y.x.x.Bytes() |
||||
yxyBytes := n.p.y.x.y.Bytes() |
||||
yyxBytes := n.p.y.y.x.Bytes() |
||||
yyyBytes := n.p.y.y.y.Bytes() |
||||
yzxBytes := n.p.y.z.x.Bytes() |
||||
yzyBytes := n.p.y.z.y.Bytes() |
||||
|
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8 |
||||
|
||||
ret := make([]byte, numBytes*12) |
||||
copy(ret[1*numBytes-len(xxxBytes):], xxxBytes) |
||||
copy(ret[2*numBytes-len(xxyBytes):], xxyBytes) |
||||
copy(ret[3*numBytes-len(xyxBytes):], xyxBytes) |
||||
copy(ret[4*numBytes-len(xyyBytes):], xyyBytes) |
||||
copy(ret[5*numBytes-len(xzxBytes):], xzxBytes) |
||||
copy(ret[6*numBytes-len(xzyBytes):], xzyBytes) |
||||
copy(ret[7*numBytes-len(yxxBytes):], yxxBytes) |
||||
copy(ret[8*numBytes-len(yxyBytes):], yxyBytes) |
||||
copy(ret[9*numBytes-len(yyxBytes):], yyxBytes) |
||||
copy(ret[10*numBytes-len(yyyBytes):], yyyBytes) |
||||
copy(ret[11*numBytes-len(yzxBytes):], yzxBytes) |
||||
copy(ret[12*numBytes-len(yzyBytes):], yzyBytes) |
||||
|
||||
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) (*GT, bool) { |
||||
// Each value is a 256-bit number.
|
||||
const numBytes = 256 / 8 |
||||
|
||||
if len(m) != 12*numBytes { |
||||
return nil, false |
||||
} |
||||
|
||||
if e.p == nil { |
||||
e.p = newGFp12(nil) |
||||
} |
||||
|
||||
e.p.x.x.x.SetBytes(m[0*numBytes : 1*numBytes]) |
||||
e.p.x.x.y.SetBytes(m[1*numBytes : 2*numBytes]) |
||||
e.p.x.y.x.SetBytes(m[2*numBytes : 3*numBytes]) |
||||
e.p.x.y.y.SetBytes(m[3*numBytes : 4*numBytes]) |
||||
e.p.x.z.x.SetBytes(m[4*numBytes : 5*numBytes]) |
||||
e.p.x.z.y.SetBytes(m[5*numBytes : 6*numBytes]) |
||||
e.p.y.x.x.SetBytes(m[6*numBytes : 7*numBytes]) |
||||
e.p.y.x.y.SetBytes(m[7*numBytes : 8*numBytes]) |
||||
e.p.y.y.x.SetBytes(m[8*numBytes : 9*numBytes]) |
||||
e.p.y.y.y.SetBytes(m[9*numBytes : 10*numBytes]) |
||||
e.p.y.z.x.SetBytes(m[10*numBytes : 11*numBytes]) |
||||
e.p.y.z.y.SetBytes(m[11*numBytes : 12*numBytes]) |
||||
|
||||
return e, true |
||||
} |
||||
|
||||
// Pair calculates an Optimal Ate pairing.
|
||||
func Pair(g1 *G1, g2 *G2) *GT { |
||||
return >{optimalAte(g2.p, g1.p, new(bnPool))} |
||||
} |
||||
|
||||
func PairingCheck(a []*G1, b []*G2) bool { |
||||
pool := new(bnPool) |
||||
e := newGFp12(pool) |
||||
e.SetOne() |
||||
for i := 0; i < len(a); i++ { |
||||
new_e := miller(b[i].p, a[i].p, pool) |
||||
e.Mul(e, new_e, pool) |
||||
} |
||||
ret := finalExponentiation(e, pool) |
||||
e.Put(pool) |
||||
return ret.IsOne() |
||||
} |
||||
|
||||
// bnPool implements a tiny cache of *big.Int objects that's used to reduce the
|
||||
// number of allocations made during processing.
|
||||
type bnPool struct { |
||||
bns []*big.Int |
||||
count int |
||||
} |
||||
|
||||
func (pool *bnPool) Get() *big.Int { |
||||
if pool == nil { |
||||
return new(big.Int) |
||||
} |
||||
|
||||
pool.count++ |
||||
l := len(pool.bns) |
||||
if l == 0 { |
||||
return new(big.Int) |
||||
} |
||||
|
||||
bn := pool.bns[l-1] |
||||
pool.bns = pool.bns[:l-1] |
||||
return bn |
||||
} |
||||
|
||||
func (pool *bnPool) Put(bn *big.Int) { |
||||
if pool == nil { |
||||
return |
||||
} |
||||
pool.bns = append(pool.bns, bn) |
||||
pool.count-- |
||||
} |
||||
|
||||
func (pool *bnPool) Count() int { |
||||
return pool.count |
||||
} |
@ -0,0 +1,304 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
import ( |
||||
"bytes" |
||||
"crypto/rand" |
||||
"math/big" |
||||
"testing" |
||||
) |
||||
|
||||
func TestGFp2Invert(t *testing.T) { |
||||
pool := new(bnPool) |
||||
|
||||
a := newGFp2(pool) |
||||
a.x.SetString("23423492374", 10) |
||||
a.y.SetString("12934872398472394827398470", 10) |
||||
|
||||
inv := newGFp2(pool) |
||||
inv.Invert(a, pool) |
||||
|
||||
b := newGFp2(pool).Mul(inv, a, pool) |
||||
if b.x.Int64() != 0 || b.y.Int64() != 1 { |
||||
t.Fatalf("bad result for a^-1*a: %s %s", b.x, b.y) |
||||
} |
||||
|
||||
a.Put(pool) |
||||
b.Put(pool) |
||||
inv.Put(pool) |
||||
|
||||
if c := pool.Count(); c > 0 { |
||||
t.Errorf("Pool count non-zero: %d\n", c) |
||||
} |
||||
} |
||||
|
||||
func isZero(n *big.Int) bool { |
||||
return new(big.Int).Mod(n, P).Int64() == 0 |
||||
} |
||||
|
||||
func isOne(n *big.Int) bool { |
||||
return new(big.Int).Mod(n, P).Int64() == 1 |
||||
} |
||||
|
||||
func TestGFp6Invert(t *testing.T) { |
||||
pool := new(bnPool) |
||||
|
||||
a := newGFp6(pool) |
||||
a.x.x.SetString("239487238491", 10) |
||||
a.x.y.SetString("2356249827341", 10) |
||||
a.y.x.SetString("082659782", 10) |
||||
a.y.y.SetString("182703523765", 10) |
||||
a.z.x.SetString("978236549263", 10) |
||||
a.z.y.SetString("64893242", 10) |
||||
|
||||
inv := newGFp6(pool) |
||||
inv.Invert(a, pool) |
||||
|
||||
b := newGFp6(pool).Mul(inv, a, pool) |
||||
if !isZero(b.x.x) || |
||||
!isZero(b.x.y) || |
||||
!isZero(b.y.x) || |
||||
!isZero(b.y.y) || |
||||
!isZero(b.z.x) || |
||||
!isOne(b.z.y) { |
||||
t.Fatalf("bad result for a^-1*a: %s", b) |
||||
} |
||||
|
||||
a.Put(pool) |
||||
b.Put(pool) |
||||
inv.Put(pool) |
||||
|
||||
if c := pool.Count(); c > 0 { |
||||
t.Errorf("Pool count non-zero: %d\n", c) |
||||
} |
||||
} |
||||
|
||||
func TestGFp12Invert(t *testing.T) { |
||||
pool := new(bnPool) |
||||
|
||||
a := newGFp12(pool) |
||||
a.x.x.x.SetString("239846234862342323958623", 10) |
||||
a.x.x.y.SetString("2359862352529835623", 10) |
||||
a.x.y.x.SetString("928836523", 10) |
||||
a.x.y.y.SetString("9856234", 10) |
||||
a.x.z.x.SetString("235635286", 10) |
||||
a.x.z.y.SetString("5628392833", 10) |
||||
a.y.x.x.SetString("252936598265329856238956532167968", 10) |
||||
a.y.x.y.SetString("23596239865236954178968", 10) |
||||
a.y.y.x.SetString("95421692834", 10) |
||||
a.y.y.y.SetString("236548", 10) |
||||
a.y.z.x.SetString("924523", 10) |
||||
a.y.z.y.SetString("12954623", 10) |
||||
|
||||
inv := newGFp12(pool) |
||||
inv.Invert(a, pool) |
||||
|
||||
b := newGFp12(pool).Mul(inv, a, pool) |
||||
if !isZero(b.x.x.x) || |
||||
!isZero(b.x.x.y) || |
||||
!isZero(b.x.y.x) || |
||||
!isZero(b.x.y.y) || |
||||
!isZero(b.x.z.x) || |
||||
!isZero(b.x.z.y) || |
||||
!isZero(b.y.x.x) || |
||||
!isZero(b.y.x.y) || |
||||
!isZero(b.y.y.x) || |
||||
!isZero(b.y.y.y) || |
||||
!isZero(b.y.z.x) || |
||||
!isOne(b.y.z.y) { |
||||
t.Fatalf("bad result for a^-1*a: %s", b) |
||||
} |
||||
|
||||
a.Put(pool) |
||||
b.Put(pool) |
||||
inv.Put(pool) |
||||
|
||||
if c := pool.Count(); c > 0 { |
||||
t.Errorf("Pool count non-zero: %d\n", c) |
||||
} |
||||
} |
||||
|
||||
func TestCurveImpl(t *testing.T) { |
||||
pool := new(bnPool) |
||||
|
||||
g := &curvePoint{ |
||||
pool.Get().SetInt64(1), |
||||
pool.Get().SetInt64(-2), |
||||
pool.Get().SetInt64(1), |
||||
pool.Get().SetInt64(0), |
||||
} |
||||
|
||||
x := pool.Get().SetInt64(32498273234) |
||||
X := newCurvePoint(pool).Mul(g, x, pool) |
||||
|
||||
y := pool.Get().SetInt64(98732423523) |
||||
Y := newCurvePoint(pool).Mul(g, y, pool) |
||||
|
||||
s1 := newCurvePoint(pool).Mul(X, y, pool).MakeAffine(pool) |
||||
s2 := newCurvePoint(pool).Mul(Y, x, pool).MakeAffine(pool) |
||||
|
||||
if s1.x.Cmp(s2.x) != 0 || |
||||
s2.x.Cmp(s1.x) != 0 { |
||||
t.Errorf("DH points don't match: (%s, %s) (%s, %s)", s1.x, s1.y, s2.x, s2.y) |
||||
} |
||||
|
||||
pool.Put(x) |
||||
X.Put(pool) |
||||
pool.Put(y) |
||||
Y.Put(pool) |
||||
s1.Put(pool) |
||||
s2.Put(pool) |
||||
g.Put(pool) |
||||
|
||||
if c := pool.Count(); c > 0 { |
||||
t.Errorf("Pool count non-zero: %d\n", c) |
||||
} |
||||
} |
||||
|
||||
func TestOrderG1(t *testing.T) { |
||||
g := new(G1).ScalarBaseMult(Order) |
||||
if !g.p.IsInfinity() { |
||||
t.Error("G1 has incorrect order") |
||||
} |
||||
|
||||
one := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) |
||||
g.Add(g, one) |
||||
g.p.MakeAffine(nil) |
||||
if g.p.x.Cmp(one.p.x) != 0 || g.p.y.Cmp(one.p.y) != 0 { |
||||
t.Errorf("1+0 != 1 in G1") |
||||
} |
||||
} |
||||
|
||||
func TestOrderG2(t *testing.T) { |
||||
g := new(G2).ScalarBaseMult(Order) |
||||
if !g.p.IsInfinity() { |
||||
t.Error("G2 has incorrect order") |
||||
} |
||||
|
||||
one := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) |
||||
g.Add(g, one) |
||||
g.p.MakeAffine(nil) |
||||
if g.p.x.x.Cmp(one.p.x.x) != 0 || |
||||
g.p.x.y.Cmp(one.p.x.y) != 0 || |
||||
g.p.y.x.Cmp(one.p.y.x) != 0 || |
||||
g.p.y.y.Cmp(one.p.y.y) != 0 { |
||||
t.Errorf("1+0 != 1 in G2") |
||||
} |
||||
} |
||||
|
||||
func TestOrderGT(t *testing.T) { |
||||
gt := Pair(&G1{curveGen}, &G2{twistGen}) |
||||
g := new(GT).ScalarMult(gt, Order) |
||||
if !g.p.IsOne() { |
||||
t.Error("GT has incorrect order") |
||||
} |
||||
} |
||||
|
||||
func TestBilinearity(t *testing.T) { |
||||
for i := 0; i < 2; i++ { |
||||
a, p1, _ := RandomG1(rand.Reader) |
||||
b, p2, _ := RandomG2(rand.Reader) |
||||
e1 := Pair(p1, p2) |
||||
|
||||
e2 := Pair(&G1{curveGen}, &G2{twistGen}) |
||||
e2.ScalarMult(e2, a) |
||||
e2.ScalarMult(e2, b) |
||||
|
||||
minusE2 := new(GT).Neg(e2) |
||||
e1.Add(e1, minusE2) |
||||
|
||||
if !e1.p.IsOne() { |
||||
t.Fatalf("bad pairing result: %s", e1) |
||||
} |
||||
} |
||||
} |
||||
|
||||
func TestG1Marshal(t *testing.T) { |
||||
g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(1)) |
||||
form := g.Marshal() |
||||
_, ok := new(G1).Unmarshal(form) |
||||
if !ok { |
||||
t.Fatalf("failed to unmarshal") |
||||
} |
||||
|
||||
g.ScalarBaseMult(Order) |
||||
form = g.Marshal() |
||||
g2, ok := new(G1).Unmarshal(form) |
||||
if !ok { |
||||
t.Fatalf("failed to unmarshal ∞") |
||||
} |
||||
if !g2.p.IsInfinity() { |
||||
t.Fatalf("∞ unmarshaled incorrectly") |
||||
} |
||||
} |
||||
|
||||
func TestG2Marshal(t *testing.T) { |
||||
g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(1)) |
||||
form := g.Marshal() |
||||
_, ok := new(G2).Unmarshal(form) |
||||
if !ok { |
||||
t.Fatalf("failed to unmarshal") |
||||
} |
||||
|
||||
g.ScalarBaseMult(Order) |
||||
form = g.Marshal() |
||||
g2, ok := new(G2).Unmarshal(form) |
||||
if !ok { |
||||
t.Fatalf("failed to unmarshal ∞") |
||||
} |
||||
if !g2.p.IsInfinity() { |
||||
t.Fatalf("∞ unmarshaled incorrectly") |
||||
} |
||||
} |
||||
|
||||
func TestG1Identity(t *testing.T) { |
||||
g := new(G1).ScalarBaseMult(new(big.Int).SetInt64(0)) |
||||
if !g.p.IsInfinity() { |
||||
t.Error("failure") |
||||
} |
||||
} |
||||
|
||||
func TestG2Identity(t *testing.T) { |
||||
g := new(G2).ScalarBaseMult(new(big.Int).SetInt64(0)) |
||||
if !g.p.IsInfinity() { |
||||
t.Error("failure") |
||||
} |
||||
} |
||||
|
||||
func TestTripartiteDiffieHellman(t *testing.T) { |
||||
a, _ := rand.Int(rand.Reader, Order) |
||||
b, _ := rand.Int(rand.Reader, Order) |
||||
c, _ := rand.Int(rand.Reader, Order) |
||||
|
||||
pa, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) |
||||
qa, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) |
||||
pb, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) |
||||
qb, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) |
||||
pc, _ := new(G1).Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) |
||||
qc, _ := new(G2).Unmarshal(new(G2).ScalarBaseMult(c).Marshal()) |
||||
|
||||
k1 := Pair(pb, qc) |
||||
k1.ScalarMult(k1, a) |
||||
k1Bytes := k1.Marshal() |
||||
|
||||
k2 := Pair(pc, qa) |
||||
k2.ScalarMult(k2, b) |
||||
k2Bytes := k2.Marshal() |
||||
|
||||
k3 := Pair(pa, qb) |
||||
k3.ScalarMult(k3, c) |
||||
k3Bytes := k3.Marshal() |
||||
|
||||
if !bytes.Equal(k1Bytes, k2Bytes) || !bytes.Equal(k2Bytes, k3Bytes) { |
||||
t.Errorf("keys didn't agree") |
||||
} |
||||
} |
||||
|
||||
func BenchmarkPairing(b *testing.B) { |
||||
for i := 0; i < b.N; i++ { |
||||
Pair(&G1{curveGen}, &G2{twistGen}) |
||||
} |
||||
} |
@ -0,0 +1,44 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
import ( |
||||
"math/big" |
||||
) |
||||
|
||||
func bigFromBase10(s string) *big.Int { |
||||
n, _ := new(big.Int).SetString(s, 10) |
||||
return n |
||||
} |
||||
|
||||
// u is the BN parameter that determines the prime: 1868033³.
|
||||
var u = bigFromBase10("4965661367192848881") |
||||
|
||||
// p is a prime over which we form a basic field: 36u⁴+36u³+24u²+6u+1.
|
||||
var P = bigFromBase10("21888242871839275222246405745257275088696311157297823662689037894645226208583") |
||||
|
||||
// Order is the number of elements in both G₁ and G₂: 36u⁴+36u³+18u²+6u+1.
|
||||
var Order = bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617") |
||||
|
||||
// xiToPMinus1Over6 is ξ^((p-1)/6) where ξ = i+9.
|
||||
var xiToPMinus1Over6 = &gfP2{bigFromBase10("16469823323077808223889137241176536799009286646108169935659301613961712198316"), bigFromBase10("8376118865763821496583973867626364092589906065868298776909617916018768340080")} |
||||
|
||||
// xiToPMinus1Over3 is ξ^((p-1)/3) where ξ = i+9.
|
||||
var xiToPMinus1Over3 = &gfP2{bigFromBase10("10307601595873709700152284273816112264069230130616436755625194854815875713954"), bigFromBase10("21575463638280843010398324269430826099269044274347216827212613867836435027261")} |
||||
|
||||
// xiToPMinus1Over2 is ξ^((p-1)/2) where ξ = i+9.
|
||||
var xiToPMinus1Over2 = &gfP2{bigFromBase10("3505843767911556378687030309984248845540243509899259641013678093033130930403"), bigFromBase10("2821565182194536844548159561693502659359617185244120367078079554186484126554")} |
||||
|
||||
// xiToPSquaredMinus1Over3 is ξ^((p²-1)/3) where ξ = i+9.
|
||||
var xiToPSquaredMinus1Over3 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556616") |
||||
|
||||
// xiTo2PSquaredMinus2Over3 is ξ^((2p²-2)/3) where ξ = i+9 (a cubic root of unity, mod p).
|
||||
var xiTo2PSquaredMinus2Over3 = bigFromBase10("2203960485148121921418603742825762020974279258880205651966") |
||||
|
||||
// xiToPSquaredMinus1Over6 is ξ^((1p²-1)/6) where ξ = i+9 (a cubic root of -1, mod p).
|
||||
var xiToPSquaredMinus1Over6 = bigFromBase10("21888242871839275220042445260109153167277707414472061641714758635765020556617") |
||||
|
||||
// xiTo2PMinus2Over3 is ξ^((2p-2)/3) where ξ = i+9.
|
||||
var xiTo2PMinus2Over3 = &gfP2{bigFromBase10("19937756971775647987995932169929341994314640652964949448313374472400716661030"), bigFromBase10("2581911344467009335267311115468803099551665605076196740867805258568234346338")} |
@ -0,0 +1,278 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
import ( |
||||
"math/big" |
||||
) |
||||
|
||||
// curvePoint implements the elliptic curve y²=x³+3. Points are kept in
|
||||
// Jacobian form and t=z² when valid. G₁ is the set of points of this curve on
|
||||
// GF(p).
|
||||
type curvePoint struct { |
||||
x, y, z, t *big.Int |
||||
} |
||||
|
||||
var curveB = new(big.Int).SetInt64(3) |
||||
|
||||
// curveGen is the generator of G₁.
|
||||
var curveGen = &curvePoint{ |
||||
new(big.Int).SetInt64(1), |
||||
new(big.Int).SetInt64(-2), |
||||
new(big.Int).SetInt64(1), |
||||
new(big.Int).SetInt64(1), |
||||
} |
||||
|
||||
func newCurvePoint(pool *bnPool) *curvePoint { |
||||
return &curvePoint{ |
||||
pool.Get(), |
||||
pool.Get(), |
||||
pool.Get(), |
||||
pool.Get(), |
||||
} |
||||
} |
||||
|
||||
func (c *curvePoint) String() string { |
||||
c.MakeAffine(new(bnPool)) |
||||
return "(" + c.x.String() + ", " + c.y.String() + ")" |
||||
} |
||||
|
||||
func (c *curvePoint) Put(pool *bnPool) { |
||||
pool.Put(c.x) |
||||
pool.Put(c.y) |
||||
pool.Put(c.z) |
||||
pool.Put(c.t) |
||||
} |
||||
|
||||
func (c *curvePoint) Set(a *curvePoint) { |
||||
c.x.Set(a.x) |
||||
c.y.Set(a.y) |
||||
c.z.Set(a.z) |
||||
c.t.Set(a.t) |
||||
} |
||||
|
||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
||||
func (c *curvePoint) IsOnCurve() bool { |
||||
yy := new(big.Int).Mul(c.y, c.y) |
||||
xxx := new(big.Int).Mul(c.x, c.x) |
||||
xxx.Mul(xxx, c.x) |
||||
yy.Sub(yy, xxx) |
||||
yy.Sub(yy, curveB) |
||||
if yy.Sign() < 0 || yy.Cmp(P) >= 0 { |
||||
yy.Mod(yy, P) |
||||
} |
||||
return yy.Sign() == 0 |
||||
} |
||||
|
||||
func (c *curvePoint) SetInfinity() { |
||||
c.z.SetInt64(0) |
||||
} |
||||
|
||||
func (c *curvePoint) IsInfinity() bool { |
||||
return c.z.Sign() == 0 |
||||
} |
||||
|
||||
func (c *curvePoint) Add(a, b *curvePoint, pool *bnPool) { |
||||
if a.IsInfinity() { |
||||
c.Set(b) |
||||
return |
||||
} |
||||
if b.IsInfinity() { |
||||
c.Set(a) |
||||
return |
||||
} |
||||
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
|
||||
// Normalize the points by replacing a = [x1:y1:z1] and b = [x2:y2:z2]
|
||||
// by [u1:s1:z1·z2] and [u2:s2:z1·z2]
|
||||
// where u1 = x1·z2², s1 = y1·z2³ and u1 = x2·z1², s2 = y2·z1³
|
||||
z1z1 := pool.Get().Mul(a.z, a.z) |
||||
z1z1.Mod(z1z1, P) |
||||
z2z2 := pool.Get().Mul(b.z, b.z) |
||||
z2z2.Mod(z2z2, P) |
||||
u1 := pool.Get().Mul(a.x, z2z2) |
||||
u1.Mod(u1, P) |
||||
u2 := pool.Get().Mul(b.x, z1z1) |
||||
u2.Mod(u2, P) |
||||
|
||||
t := pool.Get().Mul(b.z, z2z2) |
||||
t.Mod(t, P) |
||||
s1 := pool.Get().Mul(a.y, t) |
||||
s1.Mod(s1, P) |
||||
|
||||
t.Mul(a.z, z1z1) |
||||
t.Mod(t, P) |
||||
s2 := pool.Get().Mul(b.y, t) |
||||
s2.Mod(s2, P) |
||||
|
||||
// Compute x = (2h)²(s²-u1-u2)
|
||||
// where s = (s2-s1)/(u2-u1) is the slope of the line through
|
||||
// (u1,s1) and (u2,s2). The extra factor 2h = 2(u2-u1) comes from the value of z below.
|
||||
// This is also:
|
||||
// 4(s2-s1)² - 4h²(u1+u2) = 4(s2-s1)² - 4h³ - 4h²(2u1)
|
||||
// = r² - j - 2v
|
||||
// with the notations below.
|
||||
h := pool.Get().Sub(u2, u1) |
||||
xEqual := h.Sign() == 0 |
||||
|
||||
t.Add(h, h) |
||||
// i = 4h²
|
||||
i := pool.Get().Mul(t, t) |
||||
i.Mod(i, P) |
||||
// j = 4h³
|
||||
j := pool.Get().Mul(h, i) |
||||
j.Mod(j, P) |
||||
|
||||
t.Sub(s2, s1) |
||||
yEqual := t.Sign() == 0 |
||||
if xEqual && yEqual { |
||||
c.Double(a, pool) |
||||
return |
||||
} |
||||
r := pool.Get().Add(t, t) |
||||
|
||||
v := pool.Get().Mul(u1, i) |
||||
v.Mod(v, P) |
||||
|
||||
// t4 = 4(s2-s1)²
|
||||
t4 := pool.Get().Mul(r, r) |
||||
t4.Mod(t4, P) |
||||
t.Add(v, v) |
||||
t6 := pool.Get().Sub(t4, j) |
||||
c.x.Sub(t6, t) |
||||
|
||||
// Set y = -(2h)³(s1 + s*(x/4h²-u1))
|
||||
// This is also
|
||||
// y = - 2·s1·j - (s2-s1)(2x - 2i·u1) = r(v-x) - 2·s1·j
|
||||
t.Sub(v, c.x) // t7
|
||||
t4.Mul(s1, j) // t8
|
||||
t4.Mod(t4, P) |
||||
t6.Add(t4, t4) // t9
|
||||
t4.Mul(r, t) // t10
|
||||
t4.Mod(t4, P) |
||||
c.y.Sub(t4, t6) |
||||
|
||||
// Set z = 2(u2-u1)·z1·z2 = 2h·z1·z2
|
||||
t.Add(a.z, b.z) // t11
|
||||
t4.Mul(t, t) // t12
|
||||
t4.Mod(t4, P) |
||||
t.Sub(t4, z1z1) // t13
|
||||
t4.Sub(t, z2z2) // t14
|
||||
c.z.Mul(t4, h) |
||||
c.z.Mod(c.z, P) |
||||
|
||||
pool.Put(z1z1) |
||||
pool.Put(z2z2) |
||||
pool.Put(u1) |
||||
pool.Put(u2) |
||||
pool.Put(t) |
||||
pool.Put(s1) |
||||
pool.Put(s2) |
||||
pool.Put(h) |
||||
pool.Put(i) |
||||
pool.Put(j) |
||||
pool.Put(r) |
||||
pool.Put(v) |
||||
pool.Put(t4) |
||||
pool.Put(t6) |
||||
} |
||||
|
||||
func (c *curvePoint) Double(a *curvePoint, pool *bnPool) { |
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
A := pool.Get().Mul(a.x, a.x) |
||||
A.Mod(A, P) |
||||
B := pool.Get().Mul(a.y, a.y) |
||||
B.Mod(B, P) |
||||
C_ := pool.Get().Mul(B, B) |
||||
C_.Mod(C_, P) |
||||
|
||||
t := pool.Get().Add(a.x, B) |
||||
t2 := pool.Get().Mul(t, t) |
||||
t2.Mod(t2, P) |
||||
t.Sub(t2, A) |
||||
t2.Sub(t, C_) |
||||
d := pool.Get().Add(t2, t2) |
||||
t.Add(A, A) |
||||
e := pool.Get().Add(t, A) |
||||
f := pool.Get().Mul(e, e) |
||||
f.Mod(f, P) |
||||
|
||||
t.Add(d, d) |
||||
c.x.Sub(f, t) |
||||
|
||||
t.Add(C_, C_) |
||||
t2.Add(t, t) |
||||
t.Add(t2, t2) |
||||
c.y.Sub(d, c.x) |
||||
t2.Mul(e, c.y) |
||||
t2.Mod(t2, P) |
||||
c.y.Sub(t2, t) |
||||
|
||||
t.Mul(a.y, a.z) |
||||
t.Mod(t, P) |
||||
c.z.Add(t, t) |
||||
|
||||
pool.Put(A) |
||||
pool.Put(B) |
||||
pool.Put(C_) |
||||
pool.Put(t) |
||||
pool.Put(t2) |
||||
pool.Put(d) |
||||
pool.Put(e) |
||||
pool.Put(f) |
||||
} |
||||
|
||||
func (c *curvePoint) Mul(a *curvePoint, scalar *big.Int, pool *bnPool) *curvePoint { |
||||
sum := newCurvePoint(pool) |
||||
sum.SetInfinity() |
||||
t := newCurvePoint(pool) |
||||
|
||||
for i := scalar.BitLen(); i >= 0; i-- { |
||||
t.Double(sum, pool) |
||||
if scalar.Bit(i) != 0 { |
||||
sum.Add(t, a, pool) |
||||
} else { |
||||
sum.Set(t) |
||||
} |
||||
} |
||||
|
||||
c.Set(sum) |
||||
sum.Put(pool) |
||||
t.Put(pool) |
||||
return c |
||||
} |
||||
|
||||
func (c *curvePoint) MakeAffine(pool *bnPool) *curvePoint { |
||||
if words := c.z.Bits(); len(words) == 1 && words[0] == 1 { |
||||
return c |
||||
} |
||||
|
||||
zInv := pool.Get().ModInverse(c.z, P) |
||||
t := pool.Get().Mul(c.y, zInv) |
||||
t.Mod(t, P) |
||||
zInv2 := pool.Get().Mul(zInv, zInv) |
||||
zInv2.Mod(zInv2, P) |
||||
c.y.Mul(t, zInv2) |
||||
c.y.Mod(c.y, P) |
||||
t.Mul(c.x, zInv2) |
||||
t.Mod(t, P) |
||||
c.x.Set(t) |
||||
c.z.SetInt64(1) |
||||
c.t.SetInt64(1) |
||||
|
||||
pool.Put(zInv) |
||||
pool.Put(t) |
||||
pool.Put(zInv2) |
||||
|
||||
return c |
||||
} |
||||
|
||||
func (c *curvePoint) Negative(a *curvePoint) { |
||||
c.x.Set(a.x) |
||||
c.y.Neg(a.y) |
||||
c.z.Set(a.z) |
||||
c.t.SetInt64(0) |
||||
} |
@ -0,0 +1,43 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
import ( |
||||
"crypto/rand" |
||||
) |
||||
|
||||
func ExamplePair() { |
||||
// This implements the tripartite Diffie-Hellman algorithm from "A One
|
||||
// Round Protocol for Tripartite Diffie-Hellman", A. Joux.
|
||||
// http://www.springerlink.com/content/cddc57yyva0hburb/fulltext.pdf
|
||||
|
||||
// Each of three parties, a, b and c, generate a private value.
|
||||
a, _ := rand.Int(rand.Reader, Order) |
||||
b, _ := rand.Int(rand.Reader, Order) |
||||
c, _ := rand.Int(rand.Reader, Order) |
||||
|
||||
// Then each party calculates g₁ and g₂ times their private value.
|
||||
pa := new(G1).ScalarBaseMult(a) |
||||
qa := new(G2).ScalarBaseMult(a) |
||||
|
||||
pb := new(G1).ScalarBaseMult(b) |
||||
qb := new(G2).ScalarBaseMult(b) |
||||
|
||||
pc := new(G1).ScalarBaseMult(c) |
||||
qc := new(G2).ScalarBaseMult(c) |
||||
|
||||
// Now each party exchanges its public values with the other two and
|
||||
// all parties can calculate the shared key.
|
||||
k1 := Pair(pb, qc) |
||||
k1.ScalarMult(k1, a) |
||||
|
||||
k2 := Pair(pc, qa) |
||||
k2.ScalarMult(k2, b) |
||||
|
||||
k3 := Pair(pa, qb) |
||||
k3.ScalarMult(k3, c) |
||||
|
||||
// k1, k2 and k3 will all be equal.
|
||||
} |
@ -0,0 +1,200 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import ( |
||||
"math/big" |
||||
) |
||||
|
||||
// gfP12 implements the field of size p¹² as a quadratic extension of gfP6
|
||||
// where ω²=τ.
|
||||
type gfP12 struct { |
||||
x, y *gfP6 // value is xω + y
|
||||
} |
||||
|
||||
func newGFp12(pool *bnPool) *gfP12 { |
||||
return &gfP12{newGFp6(pool), newGFp6(pool)} |
||||
} |
||||
|
||||
func (e *gfP12) String() string { |
||||
return "(" + e.x.String() + "," + e.y.String() + ")" |
||||
} |
||||
|
||||
func (e *gfP12) Put(pool *bnPool) { |
||||
e.x.Put(pool) |
||||
e.y.Put(pool) |
||||
} |
||||
|
||||
func (e *gfP12) Set(a *gfP12) *gfP12 { |
||||
e.x.Set(a.x) |
||||
e.y.Set(a.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) SetZero() *gfP12 { |
||||
e.x.SetZero() |
||||
e.y.SetZero() |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) SetOne() *gfP12 { |
||||
e.x.SetZero() |
||||
e.y.SetOne() |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) Minimal() { |
||||
e.x.Minimal() |
||||
e.y.Minimal() |
||||
} |
||||
|
||||
func (e *gfP12) IsZero() bool { |
||||
e.Minimal() |
||||
return e.x.IsZero() && e.y.IsZero() |
||||
} |
||||
|
||||
func (e *gfP12) IsOne() bool { |
||||
e.Minimal() |
||||
return e.x.IsZero() && e.y.IsOne() |
||||
} |
||||
|
||||
func (e *gfP12) Conjugate(a *gfP12) *gfP12 { |
||||
e.x.Negative(a.x) |
||||
e.y.Set(a.y) |
||||
return a |
||||
} |
||||
|
||||
func (e *gfP12) Negative(a *gfP12) *gfP12 { |
||||
e.x.Negative(a.x) |
||||
e.y.Negative(a.y) |
||||
return e |
||||
} |
||||
|
||||
// Frobenius computes (xω+y)^p = x^p ω·ξ^((p-1)/6) + y^p
|
||||
func (e *gfP12) Frobenius(a *gfP12, pool *bnPool) *gfP12 { |
||||
e.x.Frobenius(a.x, pool) |
||||
e.y.Frobenius(a.y, pool) |
||||
e.x.MulScalar(e.x, xiToPMinus1Over6, pool) |
||||
return e |
||||
} |
||||
|
||||
// FrobeniusP2 computes (xω+y)^p² = x^p² ω·ξ^((p²-1)/6) + y^p²
|
||||
func (e *gfP12) FrobeniusP2(a *gfP12, pool *bnPool) *gfP12 { |
||||
e.x.FrobeniusP2(a.x) |
||||
e.x.MulGFP(e.x, xiToPSquaredMinus1Over6) |
||||
e.y.FrobeniusP2(a.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) Add(a, b *gfP12) *gfP12 { |
||||
e.x.Add(a.x, b.x) |
||||
e.y.Add(a.y, b.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) Sub(a, b *gfP12) *gfP12 { |
||||
e.x.Sub(a.x, b.x) |
||||
e.y.Sub(a.y, b.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 { |
||||
tx := newGFp6(pool) |
||||
tx.Mul(a.x, b.y, pool) |
||||
t := newGFp6(pool) |
||||
t.Mul(b.x, a.y, pool) |
||||
tx.Add(tx, t) |
||||
|
||||
ty := newGFp6(pool) |
||||
ty.Mul(a.y, b.y, pool) |
||||
t.Mul(a.x, b.x, pool) |
||||
t.MulTau(t, pool) |
||||
e.y.Add(ty, t) |
||||
e.x.Set(tx) |
||||
|
||||
tx.Put(pool) |
||||
ty.Put(pool) |
||||
t.Put(pool) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 { |
||||
e.x.Mul(e.x, b, pool) |
||||
e.y.Mul(e.y, b, pool) |
||||
return e |
||||
} |
||||
|
||||
func (c *gfP12) Exp(a *gfP12, power *big.Int, pool *bnPool) *gfP12 { |
||||
sum := newGFp12(pool) |
||||
sum.SetOne() |
||||
t := newGFp12(pool) |
||||
|
||||
for i := power.BitLen() - 1; i >= 0; i-- { |
||||
t.Square(sum, pool) |
||||
if power.Bit(i) != 0 { |
||||
sum.Mul(t, a, pool) |
||||
} else { |
||||
sum.Set(t) |
||||
} |
||||
} |
||||
|
||||
c.Set(sum) |
||||
|
||||
sum.Put(pool) |
||||
t.Put(pool) |
||||
|
||||
return c |
||||
} |
||||
|
||||
func (e *gfP12) Square(a *gfP12, pool *bnPool) *gfP12 { |
||||
// Complex squaring algorithm
|
||||
v0 := newGFp6(pool) |
||||
v0.Mul(a.x, a.y, pool) |
||||
|
||||
t := newGFp6(pool) |
||||
t.MulTau(a.x, pool) |
||||
t.Add(a.y, t) |
||||
ty := newGFp6(pool) |
||||
ty.Add(a.x, a.y) |
||||
ty.Mul(ty, t, pool) |
||||
ty.Sub(ty, v0) |
||||
t.MulTau(v0, pool) |
||||
ty.Sub(ty, t) |
||||
|
||||
e.y.Set(ty) |
||||
e.x.Double(v0) |
||||
|
||||
v0.Put(pool) |
||||
t.Put(pool) |
||||
ty.Put(pool) |
||||
|
||||
return e |
||||
} |
||||
|
||||
func (e *gfP12) Invert(a *gfP12, pool *bnPool) *gfP12 { |
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t1 := newGFp6(pool) |
||||
t2 := newGFp6(pool) |
||||
|
||||
t1.Square(a.x, pool) |
||||
t2.Square(a.y, pool) |
||||
t1.MulTau(t1, pool) |
||||
t1.Sub(t2, t1) |
||||
t2.Invert(t1, pool) |
||||
|
||||
e.x.Negative(a.x) |
||||
e.y.Set(a.y) |
||||
e.MulScalar(e, t2, pool) |
||||
|
||||
t1.Put(pool) |
||||
t2.Put(pool) |
||||
|
||||
return e |
||||
} |
@ -0,0 +1,227 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import ( |
||||
"math/big" |
||||
) |
||||
|
||||
// gfP2 implements a field of size p² as a quadratic extension of the base
|
||||
// field where i²=-1.
|
||||
type gfP2 struct { |
||||
x, y *big.Int // value is xi+y.
|
||||
} |
||||
|
||||
func newGFp2(pool *bnPool) *gfP2 { |
||||
return &gfP2{pool.Get(), pool.Get()} |
||||
} |
||||
|
||||
func (e *gfP2) String() string { |
||||
x := new(big.Int).Mod(e.x, P) |
||||
y := new(big.Int).Mod(e.y, P) |
||||
return "(" + x.String() + "," + y.String() + ")" |
||||
} |
||||
|
||||
func (e *gfP2) Put(pool *bnPool) { |
||||
pool.Put(e.x) |
||||
pool.Put(e.y) |
||||
} |
||||
|
||||
func (e *gfP2) Set(a *gfP2) *gfP2 { |
||||
e.x.Set(a.x) |
||||
e.y.Set(a.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) SetZero() *gfP2 { |
||||
e.x.SetInt64(0) |
||||
e.y.SetInt64(0) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) SetOne() *gfP2 { |
||||
e.x.SetInt64(0) |
||||
e.y.SetInt64(1) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Minimal() { |
||||
if e.x.Sign() < 0 || e.x.Cmp(P) >= 0 { |
||||
e.x.Mod(e.x, P) |
||||
} |
||||
if e.y.Sign() < 0 || e.y.Cmp(P) >= 0 { |
||||
e.y.Mod(e.y, P) |
||||
} |
||||
} |
||||
|
||||
func (e *gfP2) IsZero() bool { |
||||
return e.x.Sign() == 0 && e.y.Sign() == 0 |
||||
} |
||||
|
||||
func (e *gfP2) IsOne() bool { |
||||
if e.x.Sign() != 0 { |
||||
return false |
||||
} |
||||
words := e.y.Bits() |
||||
return len(words) == 1 && words[0] == 1 |
||||
} |
||||
|
||||
func (e *gfP2) Conjugate(a *gfP2) *gfP2 { |
||||
e.y.Set(a.y) |
||||
e.x.Neg(a.x) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Negative(a *gfP2) *gfP2 { |
||||
e.x.Neg(a.x) |
||||
e.y.Neg(a.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Add(a, b *gfP2) *gfP2 { |
||||
e.x.Add(a.x, b.x) |
||||
e.y.Add(a.y, b.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Sub(a, b *gfP2) *gfP2 { |
||||
e.x.Sub(a.x, b.x) |
||||
e.y.Sub(a.y, b.y) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Double(a *gfP2) *gfP2 { |
||||
e.x.Lsh(a.x, 1) |
||||
e.y.Lsh(a.y, 1) |
||||
return e |
||||
} |
||||
|
||||
func (c *gfP2) Exp(a *gfP2, power *big.Int, pool *bnPool) *gfP2 { |
||||
sum := newGFp2(pool) |
||||
sum.SetOne() |
||||
t := newGFp2(pool) |
||||
|
||||
for i := power.BitLen() - 1; i >= 0; i-- { |
||||
t.Square(sum, pool) |
||||
if power.Bit(i) != 0 { |
||||
sum.Mul(t, a, pool) |
||||
} else { |
||||
sum.Set(t) |
||||
} |
||||
} |
||||
|
||||
c.Set(sum) |
||||
|
||||
sum.Put(pool) |
||||
t.Put(pool) |
||||
|
||||
return c |
||||
} |
||||
|
||||
// See "Multiplication and Squaring in Pairing-Friendly Fields",
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
func (e *gfP2) Mul(a, b *gfP2, pool *bnPool) *gfP2 { |
||||
tx := pool.Get().Mul(a.x, b.y) |
||||
t := pool.Get().Mul(b.x, a.y) |
||||
tx.Add(tx, t) |
||||
tx.Mod(tx, P) |
||||
|
||||
ty := pool.Get().Mul(a.y, b.y) |
||||
t.Mul(a.x, b.x) |
||||
ty.Sub(ty, t) |
||||
e.y.Mod(ty, P) |
||||
e.x.Set(tx) |
||||
|
||||
pool.Put(tx) |
||||
pool.Put(ty) |
||||
pool.Put(t) |
||||
|
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) MulScalar(a *gfP2, b *big.Int) *gfP2 { |
||||
e.x.Mul(a.x, b) |
||||
e.y.Mul(a.y, b) |
||||
return e |
||||
} |
||||
|
||||
// MulXi sets e=ξa where ξ=i+9 and then returns e.
|
||||
func (e *gfP2) MulXi(a *gfP2, pool *bnPool) *gfP2 { |
||||
// (xi+y)(i+3) = (9x+y)i+(9y-x)
|
||||
tx := pool.Get().Lsh(a.x, 3) |
||||
tx.Add(tx, a.x) |
||||
tx.Add(tx, a.y) |
||||
|
||||
ty := pool.Get().Lsh(a.y, 3) |
||||
ty.Add(ty, a.y) |
||||
ty.Sub(ty, a.x) |
||||
|
||||
e.x.Set(tx) |
||||
e.y.Set(ty) |
||||
|
||||
pool.Put(tx) |
||||
pool.Put(ty) |
||||
|
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Square(a *gfP2, pool *bnPool) *gfP2 { |
||||
// Complex squaring algorithm:
|
||||
// (xi+b)² = (x+y)(y-x) + 2*i*x*y
|
||||
t1 := pool.Get().Sub(a.y, a.x) |
||||
t2 := pool.Get().Add(a.x, a.y) |
||||
ty := pool.Get().Mul(t1, t2) |
||||
ty.Mod(ty, P) |
||||
|
||||
t1.Mul(a.x, a.y) |
||||
t1.Lsh(t1, 1) |
||||
|
||||
e.x.Mod(t1, P) |
||||
e.y.Set(ty) |
||||
|
||||
pool.Put(t1) |
||||
pool.Put(t2) |
||||
pool.Put(ty) |
||||
|
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Invert(a *gfP2, pool *bnPool) *gfP2 { |
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
t := pool.Get() |
||||
t.Mul(a.y, a.y) |
||||
t2 := pool.Get() |
||||
t2.Mul(a.x, a.x) |
||||
t.Add(t, t2) |
||||
|
||||
inv := pool.Get() |
||||
inv.ModInverse(t, P) |
||||
|
||||
e.x.Neg(a.x) |
||||
e.x.Mul(e.x, inv) |
||||
e.x.Mod(e.x, P) |
||||
|
||||
e.y.Mul(a.y, inv) |
||||
e.y.Mod(e.y, P) |
||||
|
||||
pool.Put(t) |
||||
pool.Put(t2) |
||||
pool.Put(inv) |
||||
|
||||
return e |
||||
} |
||||
|
||||
func (e *gfP2) Real() *big.Int { |
||||
return e.x |
||||
} |
||||
|
||||
func (e *gfP2) Imag() *big.Int { |
||||
return e.y |
||||
} |
@ -0,0 +1,296 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
// For details of the algorithms used, see "Multiplication and Squaring on
|
||||
// Pairing-Friendly Fields, Devegili et al.
|
||||
// http://eprint.iacr.org/2006/471.pdf.
|
||||
|
||||
import ( |
||||
"math/big" |
||||
) |
||||
|
||||
// gfP6 implements the field of size p⁶ as a cubic extension of gfP2 where τ³=ξ
|
||||
// and ξ=i+9.
|
||||
type gfP6 struct { |
||||
x, y, z *gfP2 // value is xτ² + yτ + z
|
||||
} |
||||
|
||||
func newGFp6(pool *bnPool) *gfP6 { |
||||
return &gfP6{newGFp2(pool), newGFp2(pool), newGFp2(pool)} |
||||
} |
||||
|
||||
func (e *gfP6) String() string { |
||||
return "(" + e.x.String() + "," + e.y.String() + "," + e.z.String() + ")" |
||||
} |
||||
|
||||
func (e *gfP6) Put(pool *bnPool) { |
||||
e.x.Put(pool) |
||||
e.y.Put(pool) |
||||
e.z.Put(pool) |
||||
} |
||||
|
||||
func (e *gfP6) Set(a *gfP6) *gfP6 { |
||||
e.x.Set(a.x) |
||||
e.y.Set(a.y) |
||||
e.z.Set(a.z) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) SetZero() *gfP6 { |
||||
e.x.SetZero() |
||||
e.y.SetZero() |
||||
e.z.SetZero() |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) SetOne() *gfP6 { |
||||
e.x.SetZero() |
||||
e.y.SetZero() |
||||
e.z.SetOne() |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Minimal() { |
||||
e.x.Minimal() |
||||
e.y.Minimal() |
||||
e.z.Minimal() |
||||
} |
||||
|
||||
func (e *gfP6) IsZero() bool { |
||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsZero() |
||||
} |
||||
|
||||
func (e *gfP6) IsOne() bool { |
||||
return e.x.IsZero() && e.y.IsZero() && e.z.IsOne() |
||||
} |
||||
|
||||
func (e *gfP6) Negative(a *gfP6) *gfP6 { |
||||
e.x.Negative(a.x) |
||||
e.y.Negative(a.y) |
||||
e.z.Negative(a.z) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Frobenius(a *gfP6, pool *bnPool) *gfP6 { |
||||
e.x.Conjugate(a.x) |
||||
e.y.Conjugate(a.y) |
||||
e.z.Conjugate(a.z) |
||||
|
||||
e.x.Mul(e.x, xiTo2PMinus2Over3, pool) |
||||
e.y.Mul(e.y, xiToPMinus1Over3, pool) |
||||
return e |
||||
} |
||||
|
||||
// FrobeniusP2 computes (xτ²+yτ+z)^(p²) = xτ^(2p²) + yτ^(p²) + z
|
||||
func (e *gfP6) FrobeniusP2(a *gfP6) *gfP6 { |
||||
// τ^(2p²) = τ²τ^(2p²-2) = τ²ξ^((2p²-2)/3)
|
||||
e.x.MulScalar(a.x, xiTo2PSquaredMinus2Over3) |
||||
// τ^(p²) = ττ^(p²-1) = τξ^((p²-1)/3)
|
||||
e.y.MulScalar(a.y, xiToPSquaredMinus1Over3) |
||||
e.z.Set(a.z) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Add(a, b *gfP6) *gfP6 { |
||||
e.x.Add(a.x, b.x) |
||||
e.y.Add(a.y, b.y) |
||||
e.z.Add(a.z, b.z) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Sub(a, b *gfP6) *gfP6 { |
||||
e.x.Sub(a.x, b.x) |
||||
e.y.Sub(a.y, b.y) |
||||
e.z.Sub(a.z, b.z) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Double(a *gfP6) *gfP6 { |
||||
e.x.Double(a.x) |
||||
e.y.Double(a.y) |
||||
e.z.Double(a.z) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Mul(a, b *gfP6, pool *bnPool) *gfP6 { |
||||
// "Multiplication and Squaring on Pairing-Friendly Fields"
|
||||
// Section 4, Karatsuba method.
|
||||
// http://eprint.iacr.org/2006/471.pdf
|
||||
|
||||
v0 := newGFp2(pool) |
||||
v0.Mul(a.z, b.z, pool) |
||||
v1 := newGFp2(pool) |
||||
v1.Mul(a.y, b.y, pool) |
||||
v2 := newGFp2(pool) |
||||
v2.Mul(a.x, b.x, pool) |
||||
|
||||
t0 := newGFp2(pool) |
||||
t0.Add(a.x, a.y) |
||||
t1 := newGFp2(pool) |
||||
t1.Add(b.x, b.y) |
||||
tz := newGFp2(pool) |
||||
tz.Mul(t0, t1, pool) |
||||
|
||||
tz.Sub(tz, v1) |
||||
tz.Sub(tz, v2) |
||||
tz.MulXi(tz, pool) |
||||
tz.Add(tz, v0) |
||||
|
||||
t0.Add(a.y, a.z) |
||||
t1.Add(b.y, b.z) |
||||
ty := newGFp2(pool) |
||||
ty.Mul(t0, t1, pool) |
||||
ty.Sub(ty, v0) |
||||
ty.Sub(ty, v1) |
||||
t0.MulXi(v2, pool) |
||||
ty.Add(ty, t0) |
||||
|
||||
t0.Add(a.x, a.z) |
||||
t1.Add(b.x, b.z) |
||||
tx := newGFp2(pool) |
||||
tx.Mul(t0, t1, pool) |
||||
tx.Sub(tx, v0) |
||||
tx.Add(tx, v1) |
||||
tx.Sub(tx, v2) |
||||
|
||||
e.x.Set(tx) |
||||
e.y.Set(ty) |
||||
e.z.Set(tz) |
||||
|
||||
t0.Put(pool) |
||||
t1.Put(pool) |
||||
tx.Put(pool) |
||||
ty.Put(pool) |
||||
tz.Put(pool) |
||||
v0.Put(pool) |
||||
v1.Put(pool) |
||||
v2.Put(pool) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) MulScalar(a *gfP6, b *gfP2, pool *bnPool) *gfP6 { |
||||
e.x.Mul(a.x, b, pool) |
||||
e.y.Mul(a.y, b, pool) |
||||
e.z.Mul(a.z, b, pool) |
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) MulGFP(a *gfP6, b *big.Int) *gfP6 { |
||||
e.x.MulScalar(a.x, b) |
||||
e.y.MulScalar(a.y, b) |
||||
e.z.MulScalar(a.z, b) |
||||
return e |
||||
} |
||||
|
||||
// MulTau computes τ·(aτ²+bτ+c) = bτ²+cτ+aξ
|
||||
func (e *gfP6) MulTau(a *gfP6, pool *bnPool) { |
||||
tz := newGFp2(pool) |
||||
tz.MulXi(a.x, pool) |
||||
ty := newGFp2(pool) |
||||
ty.Set(a.y) |
||||
e.y.Set(a.z) |
||||
e.x.Set(ty) |
||||
e.z.Set(tz) |
||||
tz.Put(pool) |
||||
ty.Put(pool) |
||||
} |
||||
|
||||
func (e *gfP6) Square(a *gfP6, pool *bnPool) *gfP6 { |
||||
v0 := newGFp2(pool).Square(a.z, pool) |
||||
v1 := newGFp2(pool).Square(a.y, pool) |
||||
v2 := newGFp2(pool).Square(a.x, pool) |
||||
|
||||
c0 := newGFp2(pool).Add(a.x, a.y) |
||||
c0.Square(c0, pool) |
||||
c0.Sub(c0, v1) |
||||
c0.Sub(c0, v2) |
||||
c0.MulXi(c0, pool) |
||||
c0.Add(c0, v0) |
||||
|
||||
c1 := newGFp2(pool).Add(a.y, a.z) |
||||
c1.Square(c1, pool) |
||||
c1.Sub(c1, v0) |
||||
c1.Sub(c1, v1) |
||||
xiV2 := newGFp2(pool).MulXi(v2, pool) |
||||
c1.Add(c1, xiV2) |
||||
|
||||
c2 := newGFp2(pool).Add(a.x, a.z) |
||||
c2.Square(c2, pool) |
||||
c2.Sub(c2, v0) |
||||
c2.Add(c2, v1) |
||||
c2.Sub(c2, v2) |
||||
|
||||
e.x.Set(c2) |
||||
e.y.Set(c1) |
||||
e.z.Set(c0) |
||||
|
||||
v0.Put(pool) |
||||
v1.Put(pool) |
||||
v2.Put(pool) |
||||
c0.Put(pool) |
||||
c1.Put(pool) |
||||
c2.Put(pool) |
||||
xiV2.Put(pool) |
||||
|
||||
return e |
||||
} |
||||
|
||||
func (e *gfP6) Invert(a *gfP6, pool *bnPool) *gfP6 { |
||||
// See "Implementing cryptographic pairings", M. Scott, section 3.2.
|
||||
// ftp://136.206.11.249/pub/crypto/pairings.pdf
|
||||
|
||||
// Here we can give a short explanation of how it works: let j be a cubic root of
|
||||
// unity in GF(p²) so that 1+j+j²=0.
|
||||
// Then (xτ² + yτ + z)(xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||
// = (xτ² + yτ + z)(Cτ²+Bτ+A)
|
||||
// = (x³ξ²+y³ξ+z³-3ξxyz) = F is an element of the base field (the norm).
|
||||
//
|
||||
// On the other hand (xj²τ² + yjτ + z)(xjτ² + yj²τ + z)
|
||||
// = τ²(y²-ξxz) + τ(ξx²-yz) + (z²-ξxy)
|
||||
//
|
||||
// So that's why A = (z²-ξxy), B = (ξx²-yz), C = (y²-ξxz)
|
||||
t1 := newGFp2(pool) |
||||
|
||||
A := newGFp2(pool) |
||||
A.Square(a.z, pool) |
||||
t1.Mul(a.x, a.y, pool) |
||||
t1.MulXi(t1, pool) |
||||
A.Sub(A, t1) |
||||
|
||||
B := newGFp2(pool) |
||||
B.Square(a.x, pool) |
||||
B.MulXi(B, pool) |
||||
t1.Mul(a.y, a.z, pool) |
||||
B.Sub(B, t1) |
||||
|
||||
C_ := newGFp2(pool) |
||||
C_.Square(a.y, pool) |
||||
t1.Mul(a.x, a.z, pool) |
||||
C_.Sub(C_, t1) |
||||
|
||||
F := newGFp2(pool) |
||||
F.Mul(C_, a.y, pool) |
||||
F.MulXi(F, pool) |
||||
t1.Mul(A, a.z, pool) |
||||
F.Add(F, t1) |
||||
t1.Mul(B, a.x, pool) |
||||
t1.MulXi(t1, pool) |
||||
F.Add(F, t1) |
||||
|
||||
F.Invert(F, pool) |
||||
|
||||
e.x.Mul(C_, F, pool) |
||||
e.y.Mul(B, F, pool) |
||||
e.z.Mul(A, F, pool) |
||||
|
||||
t1.Put(pool) |
||||
A.Put(pool) |
||||
B.Put(pool) |
||||
C_.Put(pool) |
||||
F.Put(pool) |
||||
|
||||
return e |
||||
} |
@ -0,0 +1,71 @@ |
||||
package bn256 |
||||
|
||||
import ( |
||||
"testing" |
||||
|
||||
"crypto/rand" |
||||
) |
||||
|
||||
func TestRandomG2Marshal(t *testing.T) { |
||||
for i := 0; i < 10; i++ { |
||||
n, g2, err := RandomG2(rand.Reader) |
||||
if err != nil { |
||||
t.Error(err) |
||||
continue |
||||
} |
||||
t.Logf("%d: %x\n", n, g2.Marshal()) |
||||
} |
||||
} |
||||
|
||||
func TestPairings(t *testing.T) { |
||||
a1 := new(G1).ScalarBaseMult(bigFromBase10("1")) |
||||
a2 := new(G1).ScalarBaseMult(bigFromBase10("2")) |
||||
a37 := new(G1).ScalarBaseMult(bigFromBase10("37")) |
||||
an1 := new(G1).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) |
||||
|
||||
b0 := new(G2).ScalarBaseMult(bigFromBase10("0")) |
||||
b1 := new(G2).ScalarBaseMult(bigFromBase10("1")) |
||||
b2 := new(G2).ScalarBaseMult(bigFromBase10("2")) |
||||
b27 := new(G2).ScalarBaseMult(bigFromBase10("27")) |
||||
b999 := new(G2).ScalarBaseMult(bigFromBase10("999")) |
||||
bn1 := new(G2).ScalarBaseMult(bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495616")) |
||||
|
||||
p1 := Pair(a1, b1) |
||||
pn1 := Pair(a1, bn1) |
||||
np1 := Pair(an1, b1) |
||||
if pn1.String() != np1.String() { |
||||
t.Error("Pairing mismatch: e(a, -b) != e(-a, b)") |
||||
} |
||||
if !PairingCheck([]*G1{a1, an1}, []*G2{b1, b1}) { |
||||
t.Error("MultiAte check gave false negative!") |
||||
} |
||||
p0 := new(GT).Add(p1, pn1) |
||||
p0_2 := Pair(a1, b0) |
||||
if p0.String() != p0_2.String() { |
||||
t.Error("Pairing mismatch: e(a, b) * e(a, -b) != 1") |
||||
} |
||||
p0_3 := new(GT).ScalarMult(p1, bigFromBase10("21888242871839275222246405745257275088548364400416034343698204186575808495617")) |
||||
if p0.String() != p0_3.String() { |
||||
t.Error("Pairing mismatch: e(a, b) has wrong order") |
||||
} |
||||
p2 := Pair(a2, b1) |
||||
p2_2 := Pair(a1, b2) |
||||
p2_3 := new(GT).ScalarMult(p1, bigFromBase10("2")) |
||||
if p2.String() != p2_2.String() { |
||||
t.Error("Pairing mismatch: e(a, b * 2) != e(a * 2, b)") |
||||
} |
||||
if p2.String() != p2_3.String() { |
||||
t.Error("Pairing mismatch: e(a, b * 2) != e(a, b) ** 2") |
||||
} |
||||
if p2.String() == p1.String() { |
||||
t.Error("Pairing is degenerate!") |
||||
} |
||||
if PairingCheck([]*G1{a1, a1}, []*G2{b1, b1}) { |
||||
t.Error("MultiAte check gave false positive!") |
||||
} |
||||
p999 := Pair(a37, b27) |
||||
p999_2 := Pair(a1, b999) |
||||
if p999.String() != p999_2.String() { |
||||
t.Error("Pairing mismatch: e(a * 37, b * 27) != e(a, b * 999)") |
||||
} |
||||
} |
@ -0,0 +1,249 @@ |
||||
// Copyright 2012 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package bn256 |
||||
|
||||
import ( |
||||
"math/big" |
||||
) |
||||
|
||||
// twistPoint implements the elliptic curve y²=x³+3/ξ over GF(p²). Points are
|
||||
// kept in Jacobian form and t=z² when valid. The group G₂ is the set of
|
||||
// n-torsion points of this curve over GF(p²) (where n = Order)
|
||||
type twistPoint struct { |
||||
x, y, z, t *gfP2 |
||||
} |
||||
|
||||
var twistB = &gfP2{ |
||||
bigFromBase10("266929791119991161246907387137283842545076965332900288569378510910307636690"), |
||||
bigFromBase10("19485874751759354771024239261021720505790618469301721065564631296452457478373"), |
||||
} |
||||
|
||||
// twistGen is the generator of group G₂.
|
||||
var twistGen = &twistPoint{ |
||||
&gfP2{ |
||||
bigFromBase10("11559732032986387107991004021392285783925812861821192530917403151452391805634"), |
||||
bigFromBase10("10857046999023057135944570762232829481370756359578518086990519993285655852781"), |
||||
}, |
||||
&gfP2{ |
||||
bigFromBase10("4082367875863433681332203403145435568316851327593401208105741076214120093531"), |
||||
bigFromBase10("8495653923123431417604973247489272438418190587263600148770280649306958101930"), |
||||
}, |
||||
&gfP2{ |
||||
bigFromBase10("0"), |
||||
bigFromBase10("1"), |
||||
}, |
||||
&gfP2{ |
||||
bigFromBase10("0"), |
||||
bigFromBase10("1"), |
||||
}, |
||||
} |
||||
|
||||
func newTwistPoint(pool *bnPool) *twistPoint { |
||||
return &twistPoint{ |
||||
newGFp2(pool), |
||||
newGFp2(pool), |
||||
newGFp2(pool), |
||||
newGFp2(pool), |
||||
} |
||||
} |
||||
|
||||
func (c *twistPoint) String() string { |
||||
return "(" + c.x.String() + ", " + c.y.String() + ", " + c.z.String() + ")" |
||||
} |
||||
|
||||
func (c *twistPoint) Put(pool *bnPool) { |
||||
c.x.Put(pool) |
||||
c.y.Put(pool) |
||||
c.z.Put(pool) |
||||
c.t.Put(pool) |
||||
} |
||||
|
||||
func (c *twistPoint) Set(a *twistPoint) { |
||||
c.x.Set(a.x) |
||||
c.y.Set(a.y) |
||||
c.z.Set(a.z) |
||||
c.t.Set(a.t) |
||||
} |
||||
|
||||
// IsOnCurve returns true iff c is on the curve where c must be in affine form.
|
||||
func (c *twistPoint) IsOnCurve() bool { |
||||
pool := new(bnPool) |
||||
yy := newGFp2(pool).Square(c.y, pool) |
||||
xxx := newGFp2(pool).Square(c.x, pool) |
||||
xxx.Mul(xxx, c.x, pool) |
||||
yy.Sub(yy, xxx) |
||||
yy.Sub(yy, twistB) |
||||
yy.Minimal() |
||||
return yy.x.Sign() == 0 && yy.y.Sign() == 0 |
||||
} |
||||
|
||||
func (c *twistPoint) SetInfinity() { |
||||
c.z.SetZero() |
||||
} |
||||
|
||||
func (c *twistPoint) IsInfinity() bool { |
||||
return c.z.IsZero() |
||||
} |
||||
|
||||
func (c *twistPoint) Add(a, b *twistPoint, pool *bnPool) { |
||||
// For additional comments, see the same function in curve.go.
|
||||
|
||||
if a.IsInfinity() { |
||||
c.Set(b) |
||||
return |
||||
} |
||||
if b.IsInfinity() { |
||||
c.Set(a) |
||||
return |
||||
} |
||||
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
z1z1 := newGFp2(pool).Square(a.z, pool) |
||||
z2z2 := newGFp2(pool).Square(b.z, pool) |
||||
u1 := newGFp2(pool).Mul(a.x, z2z2, pool) |
||||
u2 := newGFp2(pool).Mul(b.x, z1z1, pool) |
||||
|
||||
t := newGFp2(pool).Mul(b.z, z2z2, pool) |
||||
s1 := newGFp2(pool).Mul(a.y, t, pool) |
||||
|
||||
t.Mul(a.z, z1z1, pool) |
||||
s2 := newGFp2(pool).Mul(b.y, t, pool) |
||||
|
||||
h := newGFp2(pool).Sub(u2, u1) |
||||
xEqual := h.IsZero() |
||||
|
||||
t.Add(h, h) |
||||
i := newGFp2(pool).Square(t, pool) |
||||
j := newGFp2(pool).Mul(h, i, pool) |
||||
|
||||
t.Sub(s2, s1) |
||||
yEqual := t.IsZero() |
||||
if xEqual && yEqual { |
||||
c.Double(a, pool) |
||||
return |
||||
} |
||||
r := newGFp2(pool).Add(t, t) |
||||
|
||||
v := newGFp2(pool).Mul(u1, i, pool) |
||||
|
||||
t4 := newGFp2(pool).Square(r, pool) |
||||
t.Add(v, v) |
||||
t6 := newGFp2(pool).Sub(t4, j) |
||||
c.x.Sub(t6, t) |
||||
|
||||
t.Sub(v, c.x) // t7
|
||||
t4.Mul(s1, j, pool) // t8
|
||||
t6.Add(t4, t4) // t9
|
||||
t4.Mul(r, t, pool) // t10
|
||||
c.y.Sub(t4, t6) |
||||
|
||||
t.Add(a.z, b.z) // t11
|
||||
t4.Square(t, pool) // t12
|
||||
t.Sub(t4, z1z1) // t13
|
||||
t4.Sub(t, z2z2) // t14
|
||||
c.z.Mul(t4, h, pool) |
||||
|
||||
z1z1.Put(pool) |
||||
z2z2.Put(pool) |
||||
u1.Put(pool) |
||||
u2.Put(pool) |
||||
t.Put(pool) |
||||
s1.Put(pool) |
||||
s2.Put(pool) |
||||
h.Put(pool) |
||||
i.Put(pool) |
||||
j.Put(pool) |
||||
r.Put(pool) |
||||
v.Put(pool) |
||||
t4.Put(pool) |
||||
t6.Put(pool) |
||||
} |
||||
|
||||
func (c *twistPoint) Double(a *twistPoint, pool *bnPool) { |
||||
// See http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
A := newGFp2(pool).Square(a.x, pool) |
||||
B := newGFp2(pool).Square(a.y, pool) |
||||
C_ := newGFp2(pool).Square(B, pool) |
||||
|
||||
t := newGFp2(pool).Add(a.x, B) |
||||
t2 := newGFp2(pool).Square(t, pool) |
||||
t.Sub(t2, A) |
||||
t2.Sub(t, C_) |
||||
d := newGFp2(pool).Add(t2, t2) |
||||
t.Add(A, A) |
||||
e := newGFp2(pool).Add(t, A) |
||||
f := newGFp2(pool).Square(e, pool) |
||||
|
||||
t.Add(d, d) |
||||
c.x.Sub(f, t) |
||||
|
||||
t.Add(C_, C_) |
||||
t2.Add(t, t) |
||||
t.Add(t2, t2) |
||||
c.y.Sub(d, c.x) |
||||
t2.Mul(e, c.y, pool) |
||||
c.y.Sub(t2, t) |
||||
|
||||
t.Mul(a.y, a.z, pool) |
||||
c.z.Add(t, t) |
||||
|
||||
A.Put(pool) |
||||
B.Put(pool) |
||||
C_.Put(pool) |
||||
t.Put(pool) |
||||
t2.Put(pool) |
||||
d.Put(pool) |
||||
e.Put(pool) |
||||
f.Put(pool) |
||||
} |
||||
|
||||
func (c *twistPoint) Mul(a *twistPoint, scalar *big.Int, pool *bnPool) *twistPoint { |
||||
sum := newTwistPoint(pool) |
||||
sum.SetInfinity() |
||||
t := newTwistPoint(pool) |
||||
|
||||
for i := scalar.BitLen(); i >= 0; i-- { |
||||
t.Double(sum, pool) |
||||
if scalar.Bit(i) != 0 { |
||||
sum.Add(t, a, pool) |
||||
} else { |
||||
sum.Set(t) |
||||
} |
||||
} |
||||
|
||||
c.Set(sum) |
||||
sum.Put(pool) |
||||
t.Put(pool) |
||||
return c |
||||
} |
||||
|
||||
func (c *twistPoint) MakeAffine(pool *bnPool) *twistPoint { |
||||
if c.z.IsOne() { |
||||
return c |
||||
} |
||||
|
||||
zInv := newGFp2(pool).Invert(c.z, pool) |
||||
t := newGFp2(pool).Mul(c.y, zInv, pool) |
||||
zInv2 := newGFp2(pool).Square(zInv, pool) |
||||
c.y.Mul(t, zInv2, pool) |
||||
t.Mul(c.x, zInv2, pool) |
||||
c.x.Set(t) |
||||
c.z.SetOne() |
||||
c.t.SetOne() |
||||
|
||||
zInv.Put(pool) |
||||
t.Put(pool) |
||||
zInv2.Put(pool) |
||||
|
||||
return c |
||||
} |
||||
|
||||
func (c *twistPoint) Negative(a *twistPoint, pool *bnPool) { |
||||
c.x.Set(a.x) |
||||
c.y.SetZero() |
||||
c.y.Sub(c.y, a.y) |
||||
c.z.Set(a.z) |
||||
c.t.SetZero() |
||||
} |
Loading…
Reference in new issue