diff --git a/crypto/bn256/cloudflare/bn256.go b/crypto/bn256/bn256.go similarity index 100% rename from crypto/bn256/cloudflare/bn256.go rename to crypto/bn256/bn256.go diff --git a/crypto/bn256/bn256_amd64.go b/crypto/bn256/bn256_amd64.go deleted file mode 100644 index 35b4839c24..0000000000 --- a/crypto/bn256/bn256_amd64.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// 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. -// -// 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,!appengine,!gccgo - -// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. -package bn256 - -import ( - "math/big" - - "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 { - bn256.G1 -} - -// Add sets e to a+b and then returns e. -func (e *G1) Add(a, b *G1) *G1 { - e.G1.Add(&a.G1, &b.G1) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { - e.G1.ScalarMult(&a.G1, k) - return e -} - -// 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 { - bn256.G2 -} - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - as := make([]*bn256.G1, len(a)) - for i, p := range a { - as[i] = &p.G1 - } - bs := make([]*bn256.G2, len(b)) - for i, p := range b { - bs[i] = &p.G2 - } - return bn256.PairingCheck(as, bs) -} diff --git a/crypto/bn256/bn256_other.go b/crypto/bn256/bn256_other.go deleted file mode 100644 index 81977a0a81..0000000000 --- a/crypto/bn256/bn256_other.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright 2018 The go-ethereum Authors -// This file is part of the go-ethereum library. -// -// 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. -// -// 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 appengine gccgo - -// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve. -package bn256 - -import ( - "math/big" - - "github.com/ethereum/go-ethereum/crypto/bn256/google" -) - -// 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 { - bn256.G1 -} - -// Add sets e to a+b and then returns e. -func (e *G1) Add(a, b *G1) *G1 { - e.G1.Add(&a.G1, &b.G1) - return e -} - -// ScalarMult sets e to a*k and then returns e. -func (e *G1) ScalarMult(a *G1, k *big.Int) *G1 { - e.G1.ScalarMult(&a.G1, k) - return e -} - -// 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 { - bn256.G2 -} - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - as := make([]*bn256.G1, len(a)) - for i, p := range a { - as[i] = &p.G1 - } - bs := make([]*bn256.G2, len(b)) - for i, p := range b { - bs[i] = &p.G2 - } - return bn256.PairingCheck(as, bs) -} diff --git a/crypto/bn256/cloudflare/bn256_test.go b/crypto/bn256/bn256_test.go similarity index 98% rename from crypto/bn256/cloudflare/bn256_test.go rename to crypto/bn256/bn256_test.go index 369a3edaac..0c8016d86c 100644 --- a/crypto/bn256/cloudflare/bn256_test.go +++ b/crypto/bn256/bn256_test.go @@ -1,5 +1,3 @@ -// +build amd64,!appengine,!gccgo - package bn256 import ( diff --git a/crypto/bn256/cloudflare/example_test.go b/crypto/bn256/cloudflare/example_test.go deleted file mode 100644 index 2ee545c673..0000000000 --- a/crypto/bn256/cloudflare/example_test.go +++ /dev/null @@ -1,45 +0,0 @@ -// 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. - -// +build amd64,!appengine,!gccgo - -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. -} diff --git a/crypto/bn256/cloudflare/gfp.h b/crypto/bn256/cloudflare/gfp.h deleted file mode 100644 index 66f5a4d07d..0000000000 --- a/crypto/bn256/cloudflare/gfp.h +++ /dev/null @@ -1,32 +0,0 @@ -#define storeBlock(a0,a1,a2,a3, r) \ - MOVQ a0, 0+r \ - MOVQ a1, 8+r \ - MOVQ a2, 16+r \ - MOVQ a3, 24+r - -#define loadBlock(r, a0,a1,a2,a3) \ - MOVQ 0+r, a0 \ - MOVQ 8+r, a1 \ - MOVQ 16+r, a2 \ - MOVQ 24+r, a3 - -#define gfpCarry(a0,a1,a2,a3,a4, b0,b1,b2,b3,b4) \ - \ // b = a-p - MOVQ a0, b0 \ - MOVQ a1, b1 \ - MOVQ a2, b2 \ - MOVQ a3, b3 \ - MOVQ a4, b4 \ - \ - SUBQ ·p2+0(SB), b0 \ - SBBQ ·p2+8(SB), b1 \ - SBBQ ·p2+16(SB), b2 \ - SBBQ ·p2+24(SB), b3 \ - SBBQ $0, b4 \ - \ - \ // if b is negative then return a - \ // else return b - CMOVQCC b0, a0 \ - CMOVQCC b1, a1 \ - CMOVQCC b2, a2 \ - CMOVQCC b3, a3 diff --git a/crypto/bn256/cloudflare/gfp_amd64.go b/crypto/bn256/cloudflare/gfp_amd64.go deleted file mode 100644 index ac4f1a9c62..0000000000 --- a/crypto/bn256/cloudflare/gfp_amd64.go +++ /dev/null @@ -1,15 +0,0 @@ -// +build amd64,!appengine,!gccgo - -package bn256 - -// go:noescape -func gfpNeg(c, a *gfP) - -//go:noescape -func gfpAdd(c, a, b *gfP) - -//go:noescape -func gfpSub(c, a, b *gfP) - -//go:noescape -func gfpMul(c, a, b *gfP) diff --git a/crypto/bn256/cloudflare/gfp_pure.go b/crypto/bn256/cloudflare/gfp_pure.go deleted file mode 100644 index 8fa5d30534..0000000000 --- a/crypto/bn256/cloudflare/gfp_pure.go +++ /dev/null @@ -1,19 +0,0 @@ -// +build !amd64 appengine gccgo - -package bn256 - -func gfpNeg(c, a *gfP) { - panic("unsupported architecture") -} - -func gfpAdd(c, a, b *gfP) { - panic("unsupported architecture") -} - -func gfpSub(c, a, b *gfP) { - panic("unsupported architecture") -} - -func gfpMul(c, a, b *gfP) { - panic("unsupported architecture") -} diff --git a/crypto/bn256/cloudflare/main_test.go b/crypto/bn256/cloudflare/main_test.go deleted file mode 100644 index f0d59a4041..0000000000 --- a/crypto/bn256/cloudflare/main_test.go +++ /dev/null @@ -1,73 +0,0 @@ -// +build amd64,!appengine,!gccgo - -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)") - } -} diff --git a/crypto/bn256/cloudflare/constants.go b/crypto/bn256/constants.go similarity index 100% rename from crypto/bn256/cloudflare/constants.go rename to crypto/bn256/constants.go diff --git a/crypto/bn256/cloudflare/curve.go b/crypto/bn256/curve.go similarity index 100% rename from crypto/bn256/cloudflare/curve.go rename to crypto/bn256/curve.go diff --git a/crypto/bn256/google/example_test.go b/crypto/bn256/example_test.go similarity index 100% rename from crypto/bn256/google/example_test.go rename to crypto/bn256/example_test.go diff --git a/crypto/bn256/cloudflare/gfp.go b/crypto/bn256/gfp.go similarity index 100% rename from crypto/bn256/cloudflare/gfp.go rename to crypto/bn256/gfp.go diff --git a/crypto/bn256/cloudflare/gfp12.go b/crypto/bn256/gfp12.go similarity index 100% rename from crypto/bn256/cloudflare/gfp12.go rename to crypto/bn256/gfp12.go diff --git a/crypto/bn256/cloudflare/gfp2.go b/crypto/bn256/gfp2.go similarity index 100% rename from crypto/bn256/cloudflare/gfp2.go rename to crypto/bn256/gfp2.go diff --git a/crypto/bn256/cloudflare/gfp6.go b/crypto/bn256/gfp6.go similarity index 100% rename from crypto/bn256/cloudflare/gfp6.go rename to crypto/bn256/gfp6.go diff --git a/crypto/bn256/cloudflare/gfp_amd64.s b/crypto/bn256/gfp_amd64.s similarity index 70% rename from crypto/bn256/cloudflare/gfp_amd64.s rename to crypto/bn256/gfp_amd64.s index 2d0176f2ec..3a785d200b 100644 --- a/crypto/bn256/cloudflare/gfp_amd64.s +++ b/crypto/bn256/gfp_amd64.s @@ -1,8 +1,40 @@ -// +build amd64,!appengine,!gccgo +// +build amd64,!generic -#include "gfp.h" -#include "mul.h" -#include "mul_bmi2.h" +#define storeBlock(a0,a1,a2,a3, r) \ + MOVQ a0, 0+r \ + MOVQ a1, 8+r \ + MOVQ a2, 16+r \ + MOVQ a3, 24+r + +#define loadBlock(r, a0,a1,a2,a3) \ + MOVQ 0+r, a0 \ + MOVQ 8+r, a1 \ + MOVQ 16+r, a2 \ + MOVQ 24+r, a3 + +#define gfpCarry(a0,a1,a2,a3,a4, b0,b1,b2,b3,b4) \ + \ // b = a-p + MOVQ a0, b0 \ + MOVQ a1, b1 \ + MOVQ a2, b2 \ + MOVQ a3, b3 \ + MOVQ a4, b4 \ + \ + SUBQ ·p2+0(SB), b0 \ + SBBQ ·p2+8(SB), b1 \ + SBBQ ·p2+16(SB), b2 \ + SBBQ ·p2+24(SB), b3 \ + SBBQ $0, b4 \ + \ + \ // if b is negative then return a + \ // else return b + CMOVQCC b0, a0 \ + CMOVQCC b1, a1 \ + CMOVQCC b2, a2 \ + CMOVQCC b3, a3 + +#include "mul_amd64.h" +#include "mul_bmi2_amd64.h" TEXT ·gfpNeg(SB),0,$0-16 MOVQ ·p2+0(SB), R8 diff --git a/crypto/bn256/gfp_arm64.s b/crypto/bn256/gfp_arm64.s new file mode 100644 index 0000000000..c65e80168c --- /dev/null +++ b/crypto/bn256/gfp_arm64.s @@ -0,0 +1,113 @@ +// +build arm64,!generic + +#define storeBlock(a0,a1,a2,a3, r) \ + MOVD a0, 0+r \ + MOVD a1, 8+r \ + MOVD a2, 16+r \ + MOVD a3, 24+r + +#define loadBlock(r, a0,a1,a2,a3) \ + MOVD 0+r, a0 \ + MOVD 8+r, a1 \ + MOVD 16+r, a2 \ + MOVD 24+r, a3 + +#define loadModulus(p0,p1,p2,p3) \ + MOVD ·p2+0(SB), p0 \ + MOVD ·p2+8(SB), p1 \ + MOVD ·p2+16(SB), p2 \ + MOVD ·p2+24(SB), p3 + +#include "mul_arm64.h" + +TEXT ·gfpNeg(SB),0,$0-16 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + loadModulus(R5,R6,R7,R8) + + SUBS R1, R5, R1 + SBCS R2, R6, R2 + SBCS R3, R7, R3 + SBCS R4, R8, R4 + + SUBS R5, R1, R5 + SBCS R6, R2, R6 + SBCS R7, R3, R7 + SBCS R8, R4, R8 + + CSEL CS, R5, R1, R1 + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + CSEL CS, R8, R4, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpAdd(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + loadModulus(R9,R10,R11,R12) + MOVD ZR, R0 + + ADDS R5, R1 + ADCS R6, R2 + ADCS R7, R3 + ADCS R8, R4 + ADCS ZR, R0 + + SUBS R9, R1, R5 + SBCS R10, R2, R6 + SBCS R11, R3, R7 + SBCS R12, R4, R8 + SBCS ZR, R0, R0 + + CSEL CS, R5, R1, R1 + CSEL CS, R6, R2, R2 + CSEL CS, R7, R3, R3 + CSEL CS, R8, R4, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpSub(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + loadModulus(R9,R10,R11,R12) + + SUBS R5, R1 + SBCS R6, R2 + SBCS R7, R3 + SBCS R8, R4 + + CSEL CS, ZR, R9, R9 + CSEL CS, ZR, R10, R10 + CSEL CS, ZR, R11, R11 + CSEL CS, ZR, R12, R12 + + ADDS R9, R1 + ADCS R10, R2 + ADCS R11, R3 + ADCS R12, R4 + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET + +TEXT ·gfpMul(SB),0,$0-24 + MOVD a+8(FP), R0 + loadBlock(0(R0), R1,R2,R3,R4) + MOVD b+16(FP), R0 + loadBlock(0(R0), R5,R6,R7,R8) + + mul(R9,R10,R11,R12,R13,R14,R15,R16) + gfpReduce() + + MOVD c+0(FP), R0 + storeBlock(R1,R2,R3,R4, 0(R0)) + RET diff --git a/crypto/bn256/gfp_decl.go b/crypto/bn256/gfp_decl.go new file mode 100644 index 0000000000..6a8a4fddb6 --- /dev/null +++ b/crypto/bn256/gfp_decl.go @@ -0,0 +1,18 @@ +// +build amd64,!generic arm64,!generic + +package bn256 + +// This file contains forward declarations for the architecture-specific +// assembly implementations of these functions, provided that they exist. + +// go:noescape +func gfpNeg(c, a *gfP) + +//go:noescape +func gfpAdd(c, a, b *gfP) + +//go:noescape +func gfpSub(c, a, b *gfP) + +//go:noescape +func gfpMul(c, a, b *gfP) diff --git a/crypto/bn256/gfp_generic.go b/crypto/bn256/gfp_generic.go new file mode 100644 index 0000000000..8e6be95961 --- /dev/null +++ b/crypto/bn256/gfp_generic.go @@ -0,0 +1,173 @@ +// +build !amd64,!arm64 generic + +package bn256 + +func gfpCarry(a *gfP, head uint64) { + b := &gfP{} + + var carry uint64 + for i, pi := range p2 { + ai := a[i] + bi := ai - pi - carry + b[i] = bi + carry = (pi&^ai | (pi|^ai)&bi) >> 63 + } + carry = carry &^ head + + // If b is negative, then return a. + // Else return b. + carry = -carry + ncarry := ^carry + for i := 0; i < 4; i++ { + a[i] = (a[i] & carry) | (b[i] & ncarry) + } +} + +func gfpNeg(c, a *gfP) { + var carry uint64 + for i, pi := range p2 { + ai := a[i] + ci := pi - ai - carry + c[i] = ci + carry = (ai&^pi | (ai|^pi)&ci) >> 63 + } + gfpCarry(c, 0) +} + +func gfpAdd(c, a, b *gfP) { + var carry uint64 + for i, ai := range a { + bi := b[i] + ci := ai + bi + carry + c[i] = ci + carry = (ai&bi | (ai|bi)&^ci) >> 63 + } + gfpCarry(c, carry) +} + +func gfpSub(c, a, b *gfP) { + t := &gfP{} + + var carry uint64 + for i, pi := range p2 { + bi := b[i] + ti := pi - bi - carry + t[i] = ti + carry = (bi&^pi | (bi|^pi)&ti) >> 63 + } + + carry = 0 + for i, ai := range a { + ti := t[i] + ci := ai + ti + carry + c[i] = ci + carry = (ai&ti | (ai|ti)&^ci) >> 63 + } + gfpCarry(c, carry) +} + +func mul(a, b [4]uint64) [8]uint64 { + const ( + mask16 uint64 = 0x0000ffff + mask32 uint64 = 0xffffffff + ) + + var buff [32]uint64 + for i, ai := range a { + a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 + + for j, bj := range b { + b0, b2 := bj&mask32, bj>>32 + + off := 4 * (i + j) + buff[off+0] += a0 * b0 + buff[off+1] += a1 * b0 + buff[off+2] += a2*b0 + a0*b2 + buff[off+3] += a3*b0 + a1*b2 + buff[off+4] += a2 * b2 + buff[off+5] += a3 * b2 + } + } + + for i := uint(1); i < 4; i++ { + shift := 16 * i + + var head, carry uint64 + for j := uint(0); j < 8; j++ { + block := 4 * j + + xi := buff[block] + yi := (buff[block+i] << shift) + head + zi := xi + yi + carry + buff[block] = zi + carry = (xi&yi | (xi|yi)&^zi) >> 63 + + head = buff[block+i] >> (64 - shift) + } + } + + return [8]uint64{buff[0], buff[4], buff[8], buff[12], buff[16], buff[20], buff[24], buff[28]} +} + +func halfMul(a, b [4]uint64) [4]uint64 { + const ( + mask16 uint64 = 0x0000ffff + mask32 uint64 = 0xffffffff + ) + + var buff [18]uint64 + for i, ai := range a { + a0, a1, a2, a3 := ai&mask16, (ai>>16)&mask16, (ai>>32)&mask16, ai>>48 + + for j, bj := range b { + if i+j > 3 { + break + } + b0, b2 := bj&mask32, bj>>32 + + off := 4 * (i + j) + buff[off+0] += a0 * b0 + buff[off+1] += a1 * b0 + buff[off+2] += a2*b0 + a0*b2 + buff[off+3] += a3*b0 + a1*b2 + buff[off+4] += a2 * b2 + buff[off+5] += a3 * b2 + } + } + + for i := uint(1); i < 4; i++ { + shift := 16 * i + + var head, carry uint64 + for j := uint(0); j < 4; j++ { + block := 4 * j + + xi := buff[block] + yi := (buff[block+i] << shift) + head + zi := xi + yi + carry + buff[block] = zi + carry = (xi&yi | (xi|yi)&^zi) >> 63 + + head = buff[block+i] >> (64 - shift) + } + } + + return [4]uint64{buff[0], buff[4], buff[8], buff[12]} +} + +func gfpMul(c, a, b *gfP) { + T := mul(*a, *b) + m := halfMul([4]uint64{T[0], T[1], T[2], T[3]}, np) + t := mul([4]uint64{m[0], m[1], m[2], m[3]}, p2) + + var carry uint64 + for i, Ti := range T { + ti := t[i] + zi := Ti + ti + carry + T[i] = zi + carry = (Ti&ti | (Ti|ti)&^zi) >> 63 + } + + *c = gfP{T[4], T[5], T[6], T[7]} + gfpCarry(c, carry) +} diff --git a/crypto/bn256/cloudflare/gfp_test.go b/crypto/bn256/gfp_test.go similarity index 98% rename from crypto/bn256/cloudflare/gfp_test.go rename to crypto/bn256/gfp_test.go index aff5e0531f..16ab2a8410 100644 --- a/crypto/bn256/cloudflare/gfp_test.go +++ b/crypto/bn256/gfp_test.go @@ -1,5 +1,3 @@ -// +build amd64,!appengine,!gccgo - package bn256 import ( diff --git a/crypto/bn256/google/bn256.go b/crypto/bn256/google/bn256.go deleted file mode 100644 index 5da83e033a..0000000000 --- a/crypto/bn256/google/bn256.go +++ /dev/null @@ -1,447 +0,0 @@ -// 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" - "errors" - "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) ([]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 = newCurvePoint(nil) - } - e.p.x.SetBytes(m[0*numBytes : 1*numBytes]) - if e.p.x.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.y.SetBytes(m[1*numBytes : 2*numBytes]) - if e.p.y.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - // Ensure the point is on the curve - 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, 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 -} - -// 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) ([]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 = newTwistPoint(nil) - } - e.p.x.x.SetBytes(m[0*numBytes : 1*numBytes]) - if e.p.x.x.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.x.y.SetBytes(m[1*numBytes : 2*numBytes]) - if e.p.x.y.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.y.x.SetBytes(m[2*numBytes : 3*numBytes]) - if e.p.y.x.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - e.p.y.y.SetBytes(m[3*numBytes : 4*numBytes]) - if e.p.y.y.Cmp(P) >= 0 { - return nil, errors.New("bn256: coordinate exceeds modulus") - } - // Ensure the point is on the curve - 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, 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 -} - -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))} -} - -// PairingCheck calculates the Optimal Ate pairing for a set of points. -func PairingCheck(a []*G1, b []*G2) bool { - pool := new(bnPool) - - acc := newGFp12(pool) - 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, pool), pool) - } - ret := finalExponentiation(acc, pool) - acc.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 -} diff --git a/crypto/bn256/google/bn256_test.go b/crypto/bn256/google/bn256_test.go deleted file mode 100644 index a4497ada9b..0000000000 --- a/crypto/bn256/google/bn256_test.go +++ /dev/null @@ -1,311 +0,0 @@ -// 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() - _, err := new(G1).Unmarshal(form) - if err != nil { - t.Fatalf("failed to unmarshal") - } - - g.ScalarBaseMult(Order) - form = g.Marshal() - - g2 := new(G1) - if _, err = g2.Unmarshal(form); err != nil { - 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() - _, err := new(G2).Unmarshal(form) - if err != nil { - t.Fatalf("failed to unmarshal") - } - - g.ScalarBaseMult(Order) - form = g.Marshal() - g2 := new(G2) - if _, err = g2.Unmarshal(form); err != nil { - 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) - pa.Unmarshal(new(G1).ScalarBaseMult(a).Marshal()) - qa := new(G2) - qa.Unmarshal(new(G2).ScalarBaseMult(a).Marshal()) - pb := new(G1) - pb.Unmarshal(new(G1).ScalarBaseMult(b).Marshal()) - qb := new(G2) - qb.Unmarshal(new(G2).ScalarBaseMult(b).Marshal()) - pc := new(G1) - pc.Unmarshal(new(G1).ScalarBaseMult(c).Marshal()) - qc := new(G2) - qc.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}) - } -} diff --git a/crypto/bn256/google/constants.go b/crypto/bn256/google/constants.go deleted file mode 100644 index ab649d7f3f..0000000000 --- a/crypto/bn256/google/constants.go +++ /dev/null @@ -1,44 +0,0 @@ -// 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")} diff --git a/crypto/bn256/google/curve.go b/crypto/bn256/google/curve.go deleted file mode 100644 index 3e679fdc7e..0000000000 --- a/crypto/bn256/google/curve.go +++ /dev/null @@ -1,278 +0,0 @@ -// 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) -} diff --git a/crypto/bn256/google/gfp12.go b/crypto/bn256/google/gfp12.go deleted file mode 100644 index f084eddf21..0000000000 --- a/crypto/bn256/google/gfp12.go +++ /dev/null @@ -1,200 +0,0 @@ -// 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 -} diff --git a/crypto/bn256/google/gfp2.go b/crypto/bn256/google/gfp2.go deleted file mode 100644 index 3981f6cb4f..0000000000 --- a/crypto/bn256/google/gfp2.go +++ /dev/null @@ -1,227 +0,0 @@ -// 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 -} diff --git a/crypto/bn256/google/gfp6.go b/crypto/bn256/google/gfp6.go deleted file mode 100644 index 218856617c..0000000000 --- a/crypto/bn256/google/gfp6.go +++ /dev/null @@ -1,296 +0,0 @@ -// 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 -} diff --git a/crypto/bn256/google/optate.go b/crypto/bn256/google/optate.go deleted file mode 100644 index 9d6957062e..0000000000 --- a/crypto/bn256/google/optate.go +++ /dev/null @@ -1,397 +0,0 @@ -// 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 - -func lineFunctionAdd(r, p *twistPoint, q *curvePoint, r2 *gfP2, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { - // See the mixed addition algorithm from "Faster Computation of the - // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf - - B := newGFp2(pool).Mul(p.x, r.t, pool) - - D := newGFp2(pool).Add(p.y, r.z) - D.Square(D, pool) - D.Sub(D, r2) - D.Sub(D, r.t) - D.Mul(D, r.t, pool) - - H := newGFp2(pool).Sub(B, r.x) - I := newGFp2(pool).Square(H, pool) - - E := newGFp2(pool).Add(I, I) - E.Add(E, E) - - J := newGFp2(pool).Mul(H, E, pool) - - L1 := newGFp2(pool).Sub(D, r.y) - L1.Sub(L1, r.y) - - V := newGFp2(pool).Mul(r.x, E, pool) - - rOut = newTwistPoint(pool) - rOut.x.Square(L1, pool) - rOut.x.Sub(rOut.x, J) - rOut.x.Sub(rOut.x, V) - rOut.x.Sub(rOut.x, V) - - rOut.z.Add(r.z, H) - rOut.z.Square(rOut.z, pool) - rOut.z.Sub(rOut.z, r.t) - rOut.z.Sub(rOut.z, I) - - t := newGFp2(pool).Sub(V, rOut.x) - t.Mul(t, L1, pool) - t2 := newGFp2(pool).Mul(r.y, J, pool) - t2.Add(t2, t2) - rOut.y.Sub(t, t2) - - rOut.t.Square(rOut.z, pool) - - t.Add(p.y, rOut.z) - t.Square(t, pool) - t.Sub(t, r2) - t.Sub(t, rOut.t) - - t2.Mul(L1, p.x, pool) - t2.Add(t2, t2) - a = newGFp2(pool) - a.Sub(t2, t) - - c = newGFp2(pool) - c.MulScalar(rOut.z, q.y) - c.Add(c, c) - - b = newGFp2(pool) - b.SetZero() - b.Sub(b, L1) - b.MulScalar(b, q.x) - b.Add(b, b) - - B.Put(pool) - D.Put(pool) - H.Put(pool) - I.Put(pool) - E.Put(pool) - J.Put(pool) - L1.Put(pool) - V.Put(pool) - t.Put(pool) - t2.Put(pool) - - return -} - -func lineFunctionDouble(r *twistPoint, q *curvePoint, pool *bnPool) (a, b, c *gfP2, rOut *twistPoint) { - // See the doubling algorithm for a=0 from "Faster Computation of the - // Tate Pairing", http://arxiv.org/pdf/0904.0854v3.pdf - - A := newGFp2(pool).Square(r.x, pool) - B := newGFp2(pool).Square(r.y, pool) - C_ := newGFp2(pool).Square(B, pool) - - D := newGFp2(pool).Add(r.x, B) - D.Square(D, pool) - D.Sub(D, A) - D.Sub(D, C_) - D.Add(D, D) - - E := newGFp2(pool).Add(A, A) - E.Add(E, A) - - G := newGFp2(pool).Square(E, pool) - - rOut = newTwistPoint(pool) - rOut.x.Sub(G, D) - rOut.x.Sub(rOut.x, D) - - rOut.z.Add(r.y, r.z) - rOut.z.Square(rOut.z, pool) - rOut.z.Sub(rOut.z, B) - rOut.z.Sub(rOut.z, r.t) - - rOut.y.Sub(D, rOut.x) - rOut.y.Mul(rOut.y, E, pool) - t := newGFp2(pool).Add(C_, C_) - t.Add(t, t) - t.Add(t, t) - rOut.y.Sub(rOut.y, t) - - rOut.t.Square(rOut.z, pool) - - t.Mul(E, r.t, pool) - t.Add(t, t) - b = newGFp2(pool) - b.SetZero() - b.Sub(b, t) - b.MulScalar(b, q.x) - - a = newGFp2(pool) - a.Add(r.x, E) - a.Square(a, pool) - a.Sub(a, A) - a.Sub(a, G) - t.Add(B, B) - t.Add(t, t) - a.Sub(a, t) - - c = newGFp2(pool) - c.Mul(rOut.z, r.t, pool) - c.Add(c, c) - c.MulScalar(c, q.y) - - A.Put(pool) - B.Put(pool) - C_.Put(pool) - D.Put(pool) - E.Put(pool) - G.Put(pool) - t.Put(pool) - - return -} - -func mulLine(ret *gfP12, a, b, c *gfP2, pool *bnPool) { - a2 := newGFp6(pool) - a2.x.SetZero() - a2.y.Set(a) - a2.z.Set(b) - a2.Mul(a2, ret.x, pool) - t3 := newGFp6(pool).MulScalar(ret.y, c, pool) - - t := newGFp2(pool) - t.Add(b, c) - t2 := newGFp6(pool) - t2.x.SetZero() - t2.y.Set(a) - t2.z.Set(t) - ret.x.Add(ret.x, ret.y) - - ret.y.Set(t3) - - ret.x.Mul(ret.x, t2, pool) - ret.x.Sub(ret.x, a2) - ret.x.Sub(ret.x, ret.y) - a2.MulTau(a2, pool) - ret.y.Add(ret.y, a2) - - a2.Put(pool) - t3.Put(pool) - t2.Put(pool) - t.Put(pool) -} - -// sixuPlus2NAF is 6u+2 in non-adjacent form. -var sixuPlus2NAF = []int8{0, 0, 0, 1, 0, 1, 0, -1, 0, 0, 1, -1, 0, 0, 1, 0, - 0, 1, 1, 0, -1, 0, 0, 1, 0, -1, 0, 0, 0, 0, 1, 1, - 1, 0, 0, -1, 0, 0, 1, 0, 0, 0, 0, 0, -1, 0, 0, 1, - 1, 0, 0, -1, 0, 0, 0, 1, 1, 0, -1, 0, 0, 1, 0, 1, 1} - -// miller implements the Miller loop for calculating the Optimal Ate pairing. -// See algorithm 1 from http://cryptojedi.org/papers/dclxvi-20100714.pdf -func miller(q *twistPoint, p *curvePoint, pool *bnPool) *gfP12 { - ret := newGFp12(pool) - ret.SetOne() - - aAffine := newTwistPoint(pool) - aAffine.Set(q) - aAffine.MakeAffine(pool) - - bAffine := newCurvePoint(pool) - bAffine.Set(p) - bAffine.MakeAffine(pool) - - minusA := newTwistPoint(pool) - minusA.Negative(aAffine, pool) - - r := newTwistPoint(pool) - r.Set(aAffine) - - r2 := newGFp2(pool) - r2.Square(aAffine.y, pool) - - for i := len(sixuPlus2NAF) - 1; i > 0; i-- { - a, b, c, newR := lineFunctionDouble(r, bAffine, pool) - if i != len(sixuPlus2NAF)-1 { - ret.Square(ret, pool) - } - - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - - switch sixuPlus2NAF[i-1] { - case 1: - a, b, c, newR = lineFunctionAdd(r, aAffine, bAffine, r2, pool) - case -1: - a, b, c, newR = lineFunctionAdd(r, minusA, bAffine, r2, pool) - default: - continue - } - - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - } - - // In order to calculate Q1 we have to convert q from the sextic twist - // to the full GF(p^12) group, apply the Frobenius there, and convert - // back. - // - // The twist isomorphism is (x', y') -> (xω², yω³). If we consider just - // x for a moment, then after applying the Frobenius, we have x̄ω^(2p) - // where x̄ is the conjugate of x. If we are going to apply the inverse - // isomorphism we need a value with a single coefficient of ω² so we - // rewrite this as x̄ω^(2p-2)ω². ξ⁶ = ω and, due to the construction of - // p, 2p-2 is a multiple of six. Therefore we can rewrite as - // x̄ξ^((p-1)/3)ω² and applying the inverse isomorphism eliminates the - // ω². - // - // A similar argument can be made for the y value. - - q1 := newTwistPoint(pool) - q1.x.Conjugate(aAffine.x) - q1.x.Mul(q1.x, xiToPMinus1Over3, pool) - q1.y.Conjugate(aAffine.y) - q1.y.Mul(q1.y, xiToPMinus1Over2, pool) - q1.z.SetOne() - q1.t.SetOne() - - // For Q2 we are applying the p² Frobenius. The two conjugations cancel - // out and we are left only with the factors from the isomorphism. In - // the case of x, we end up with a pure number which is why - // xiToPSquaredMinus1Over3 is ∈ GF(p). With y we get a factor of -1. We - // ignore this to end up with -Q2. - - minusQ2 := newTwistPoint(pool) - minusQ2.x.MulScalar(aAffine.x, xiToPSquaredMinus1Over3) - minusQ2.y.Set(aAffine.y) - minusQ2.z.SetOne() - minusQ2.t.SetOne() - - r2.Square(q1.y, pool) - a, b, c, newR := lineFunctionAdd(r, q1, bAffine, r2, pool) - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - - r2.Square(minusQ2.y, pool) - a, b, c, newR = lineFunctionAdd(r, minusQ2, bAffine, r2, pool) - mulLine(ret, a, b, c, pool) - a.Put(pool) - b.Put(pool) - c.Put(pool) - r.Put(pool) - r = newR - - aAffine.Put(pool) - bAffine.Put(pool) - minusA.Put(pool) - r.Put(pool) - r2.Put(pool) - - return ret -} - -// finalExponentiation computes the (p¹²-1)/Order-th power of an element of -// GF(p¹²) to obtain an element of GT (steps 13-15 of algorithm 1 from -// http://cryptojedi.org/papers/dclxvi-20100714.pdf) -func finalExponentiation(in *gfP12, pool *bnPool) *gfP12 { - t1 := newGFp12(pool) - - // This is the p^6-Frobenius - t1.x.Negative(in.x) - t1.y.Set(in.y) - - inv := newGFp12(pool) - inv.Invert(in, pool) - t1.Mul(t1, inv, pool) - - t2 := newGFp12(pool).FrobeniusP2(t1, pool) - t1.Mul(t1, t2, pool) - - fp := newGFp12(pool).Frobenius(t1, pool) - fp2 := newGFp12(pool).FrobeniusP2(t1, pool) - fp3 := newGFp12(pool).Frobenius(fp2, pool) - - fu, fu2, fu3 := newGFp12(pool), newGFp12(pool), newGFp12(pool) - fu.Exp(t1, u, pool) - fu2.Exp(fu, u, pool) - fu3.Exp(fu2, u, pool) - - y3 := newGFp12(pool).Frobenius(fu, pool) - fu2p := newGFp12(pool).Frobenius(fu2, pool) - fu3p := newGFp12(pool).Frobenius(fu3, pool) - y2 := newGFp12(pool).FrobeniusP2(fu2, pool) - - y0 := newGFp12(pool) - y0.Mul(fp, fp2, pool) - y0.Mul(y0, fp3, pool) - - y1, y4, y5 := newGFp12(pool), newGFp12(pool), newGFp12(pool) - y1.Conjugate(t1) - y5.Conjugate(fu2) - y3.Conjugate(y3) - y4.Mul(fu, fu2p, pool) - y4.Conjugate(y4) - - y6 := newGFp12(pool) - y6.Mul(fu3, fu3p, pool) - y6.Conjugate(y6) - - t0 := newGFp12(pool) - t0.Square(y6, pool) - t0.Mul(t0, y4, pool) - t0.Mul(t0, y5, pool) - t1.Mul(y3, y5, pool) - t1.Mul(t1, t0, pool) - t0.Mul(t0, y2, pool) - t1.Square(t1, pool) - t1.Mul(t1, t0, pool) - t1.Square(t1, pool) - t0.Mul(t1, y1, pool) - t1.Mul(t1, y0, pool) - t0.Square(t0, pool) - t0.Mul(t0, t1, pool) - - inv.Put(pool) - t1.Put(pool) - t2.Put(pool) - fp.Put(pool) - fp2.Put(pool) - fp3.Put(pool) - fu.Put(pool) - fu2.Put(pool) - fu3.Put(pool) - fu2p.Put(pool) - fu3p.Put(pool) - y0.Put(pool) - y1.Put(pool) - y2.Put(pool) - y3.Put(pool) - y4.Put(pool) - y5.Put(pool) - y6.Put(pool) - - return t0 -} - -func optimalAte(a *twistPoint, b *curvePoint, pool *bnPool) *gfP12 { - e := miller(a, b, pool) - ret := finalExponentiation(e, pool) - e.Put(pool) - - if a.IsInfinity() || b.IsInfinity() { - ret.SetOne() - } - return ret -} diff --git a/crypto/bn256/google/twist.go b/crypto/bn256/google/twist.go deleted file mode 100644 index 1f5a4d9deb..0000000000 --- a/crypto/bn256/google/twist.go +++ /dev/null @@ -1,255 +0,0 @@ -// 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() - - if yy.x.Sign() != 0 || yy.y.Sign() != 0 { - return false - } - cneg := newTwistPoint(pool) - cneg.Mul(c, Order, pool) - return cneg.z.IsZero() -} - -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() -} diff --git a/crypto/bn256/google/main_test.go b/crypto/bn256/main_test.go similarity index 100% rename from crypto/bn256/google/main_test.go rename to crypto/bn256/main_test.go diff --git a/crypto/bn256/cloudflare/mul.h b/crypto/bn256/mul_amd64.h similarity index 100% rename from crypto/bn256/cloudflare/mul.h rename to crypto/bn256/mul_amd64.h diff --git a/crypto/bn256/mul_arm64.h b/crypto/bn256/mul_arm64.h new file mode 100644 index 0000000000..75d5221731 --- /dev/null +++ b/crypto/bn256/mul_arm64.h @@ -0,0 +1,133 @@ +#define mul(c0,c1,c2,c3,c4,c5,c6,c7) \ + MUL R1, R5, c0 \ + UMULH R1, R5, c1 \ + MUL R1, R6, R0 \ + ADDS R0, c1 \ + UMULH R1, R6, c2 \ + MUL R1, R7, R0 \ + ADCS R0, c2 \ + UMULH R1, R7, c3 \ + MUL R1, R8, R0 \ + ADCS R0, c3 \ + UMULH R1, R8, c4 \ + ADCS ZR, c4 \ + \ + MUL R2, R5, R25 \ + UMULH R2, R5, R26 \ + MUL R2, R6, R0 \ + ADDS R0, R26 \ + UMULH R2, R6, R27 \ + MUL R2, R7, R0 \ + ADCS R0, R27 \ + UMULH R2, R7, R29 \ + MUL R2, R8, R0 \ + ADCS R0, R29 \ + UMULH R2, R8, c5 \ + ADCS ZR, c5 \ + ADDS R25, c1 \ + ADCS R26, c2 \ + ADCS R27, c3 \ + ADCS R29, c4 \ + ADCS ZR, c5 \ + \ + MUL R3, R5, R25 \ + UMULH R3, R5, R26 \ + MUL R3, R6, R0 \ + ADDS R0, R26 \ + UMULH R3, R6, R27 \ + MUL R3, R7, R0 \ + ADCS R0, R27 \ + UMULH R3, R7, R29 \ + MUL R3, R8, R0 \ + ADCS R0, R29 \ + UMULH R3, R8, c6 \ + ADCS ZR, c6 \ + ADDS R25, c2 \ + ADCS R26, c3 \ + ADCS R27, c4 \ + ADCS R29, c5 \ + ADCS ZR, c6 \ + \ + MUL R4, R5, R25 \ + UMULH R4, R5, R26 \ + MUL R4, R6, R0 \ + ADDS R0, R26 \ + UMULH R4, R6, R27 \ + MUL R4, R7, R0 \ + ADCS R0, R27 \ + UMULH R4, R7, R29 \ + MUL R4, R8, R0 \ + ADCS R0, R29 \ + UMULH R4, R8, c7 \ + ADCS ZR, c7 \ + ADDS R25, c3 \ + ADCS R26, c4 \ + ADCS R27, c5 \ + ADCS R29, c6 \ + ADCS ZR, c7 + +#define gfpReduce() \ + \ // m = (T * N') mod R, store m in R1:R2:R3:R4 + MOVD ·np+0(SB), R17 \ + MOVD ·np+8(SB), R18 \ + MOVD ·np+16(SB), R19 \ + MOVD ·np+24(SB), R20 \ + \ + MUL R9, R17, R1 \ + UMULH R9, R17, R2 \ + MUL R9, R18, R0 \ + ADDS R0, R2 \ + UMULH R9, R18, R3 \ + MUL R9, R19, R0 \ + ADCS R0, R3 \ + UMULH R9, R19, R4 \ + MUL R9, R20, R0 \ + ADCS R0, R4 \ + \ + MUL R10, R17, R21 \ + UMULH R10, R17, R22 \ + MUL R10, R18, R0 \ + ADDS R0, R22 \ + UMULH R10, R18, R23 \ + MUL R10, R19, R0 \ + ADCS R0, R23 \ + ADDS R21, R2 \ + ADCS R22, R3 \ + ADCS R23, R4 \ + \ + MUL R11, R17, R21 \ + UMULH R11, R17, R22 \ + MUL R11, R18, R0 \ + ADDS R0, R22 \ + ADDS R21, R3 \ + ADCS R22, R4 \ + \ + MUL R12, R17, R21 \ + ADDS R21, R4 \ + \ + \ // m * N + loadModulus(R5,R6,R7,R8) \ + mul(R17,R18,R19,R20,R21,R22,R23,R24) \ + \ + \ // Add the 512-bit intermediate to m*N + MOVD ZR, R25 \ + ADDS R9, R17 \ + ADCS R10, R18 \ + ADCS R11, R19 \ + ADCS R12, R20 \ + ADCS R13, R21 \ + ADCS R14, R22 \ + ADCS R15, R23 \ + ADCS R16, R24 \ + ADCS ZR, R25 \ + \ + \ // Our output is R21:R22:R23:R24. Reduce mod p if necessary. + SUBS R5, R21, R10 \ + SBCS R6, R22, R11 \ + SBCS R7, R23, R12 \ + SBCS R8, R24, R13 \ + \ + CSEL CS, R10, R21, R1 \ + CSEL CS, R11, R22, R2 \ + CSEL CS, R12, R23, R3 \ + CSEL CS, R13, R24, R4 diff --git a/crypto/bn256/cloudflare/mul_bmi2.h b/crypto/bn256/mul_bmi2_amd64.h similarity index 100% rename from crypto/bn256/cloudflare/mul_bmi2.h rename to crypto/bn256/mul_bmi2_amd64.h diff --git a/crypto/bn256/cloudflare/optate.go b/crypto/bn256/optate.go similarity index 100% rename from crypto/bn256/cloudflare/optate.go rename to crypto/bn256/optate.go diff --git a/crypto/bn256/cloudflare/twist.go b/crypto/bn256/twist.go similarity index 100% rename from crypto/bn256/cloudflare/twist.go rename to crypto/bn256/twist.go