mirror of
https://github.com/arnaucube/cryptofun.git
synced 2026-02-28 05:16:46 +01:00
bn128 G1 and G2 operations
This commit is contained in:
88
bn128/bn128.go
Normal file
88
bn128/bn128.go
Normal file
@@ -0,0 +1,88 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type Bn128 struct {
|
||||
Q *big.Int
|
||||
R *big.Int
|
||||
Gg1 [2]*big.Int
|
||||
Gg2 [2][2]*big.Int
|
||||
NonResidueFq2 *big.Int
|
||||
NonResidueFq6 [2]*big.Int
|
||||
Fq1 Fq
|
||||
Fq2 Fq2
|
||||
Fq6 Fq6
|
||||
Fq12 Fq12
|
||||
G1 G1
|
||||
G2 G2
|
||||
}
|
||||
|
||||
func NewBn128() (Bn128, error) {
|
||||
var b Bn128
|
||||
q, ok := new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10) // i
|
||||
if !ok {
|
||||
return b, errors.New("err with q")
|
||||
}
|
||||
b.Q = q
|
||||
r, ok := new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) // i
|
||||
if !ok {
|
||||
return b, errors.New("err with r")
|
||||
}
|
||||
b.R = r
|
||||
|
||||
b.Gg1 = [2]*big.Int{
|
||||
big.NewInt(int64(1)),
|
||||
big.NewInt(int64(2)),
|
||||
}
|
||||
|
||||
g2_00, ok := new(big.Int).SetString("10857046999023057135944570762232829481370756359578518086990519993285655852781", 10)
|
||||
if !ok {
|
||||
return b, errors.New("err with g2_00")
|
||||
}
|
||||
g2_01, ok := new(big.Int).SetString("11559732032986387107991004021392285783925812861821192530917403151452391805634", 10)
|
||||
if !ok {
|
||||
return b, errors.New("err with g2_00")
|
||||
}
|
||||
g2_10, ok := new(big.Int).SetString("8495653923123431417604973247489272438418190587263600148770280649306958101930", 10)
|
||||
if !ok {
|
||||
return b, errors.New("err with g2_00")
|
||||
}
|
||||
g2_11, ok := new(big.Int).SetString("4082367875863433681332203403145435568316851327593401208105741076214120093531", 10)
|
||||
if !ok {
|
||||
return b, errors.New("err with g2_00")
|
||||
}
|
||||
g2_0 := [2]*big.Int{
|
||||
g2_00,
|
||||
g2_01,
|
||||
}
|
||||
g2_1 := [2]*big.Int{
|
||||
g2_10,
|
||||
g2_11,
|
||||
}
|
||||
b.Gg2 = [2][2]*big.Int{
|
||||
g2_0,
|
||||
g2_1,
|
||||
}
|
||||
|
||||
b.Fq1 = NewFq(q)
|
||||
b.NonResidueFq2, ok = new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208582", 10) // i
|
||||
if !ok {
|
||||
return b, errors.New("err with nonResidueFq2")
|
||||
}
|
||||
b.NonResidueFq6 = [2]*big.Int{
|
||||
big.NewInt(int64(9)),
|
||||
big.NewInt(int64(1)),
|
||||
}
|
||||
|
||||
b.Fq2 = Fq2{b.Fq1, b.NonResidueFq2}
|
||||
b.Fq6 = Fq6{b.Fq2, b.NonResidueFq6}
|
||||
b.Fq12 = Fq12{b.Fq6, b.Fq2, b.NonResidueFq6}
|
||||
|
||||
b.G1 = NewG1(b.Fq1, b.Gg1)
|
||||
b.G2 = NewG2(b.Fq2, b.Gg2)
|
||||
|
||||
return b, nil
|
||||
}
|
||||
17
bn128/fq.go
17
bn128/fq.go
@@ -1,6 +1,7 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
@@ -56,6 +57,10 @@ func (fq Fq) Mul(a, b *big.Int) *big.Int {
|
||||
return new(big.Int).Mod(m, fq.Q)
|
||||
}
|
||||
|
||||
func (fq Fq) MulScalar(base, e *big.Int) *big.Int {
|
||||
return fq.Mul(base, e)
|
||||
}
|
||||
|
||||
// Inverse returns the inverse on the Fq
|
||||
func (fq Fq) Inverse(a *big.Int) *big.Int {
|
||||
return new(big.Int).ModInverse(a, fq.Q)
|
||||
@@ -72,3 +77,15 @@ func (fq Fq) Square(a *big.Int) *big.Int {
|
||||
m := new(big.Int).Mul(a, a)
|
||||
return new(big.Int).Mod(m, fq.Q)
|
||||
}
|
||||
|
||||
func (fq Fq) IsZero(a *big.Int) bool {
|
||||
return bytes.Equal(a.Bytes(), fq.Zero().Bytes())
|
||||
}
|
||||
|
||||
func (fq Fq) Copy(a *big.Int) *big.Int {
|
||||
return new(big.Int).SetBytes(a.Bytes())
|
||||
}
|
||||
|
||||
func (fq Fq) Affine(a *big.Int) *big.Int {
|
||||
return a
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
@@ -82,6 +83,22 @@ func (fq12 Fq12) Mul(a, b [2][3][2]*big.Int) [2][3][2]*big.Int {
|
||||
}
|
||||
}
|
||||
|
||||
func (fq12 Fq12) MulScalar(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
||||
res := fq12.Zero()
|
||||
rem := e
|
||||
exp := base
|
||||
|
||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
// if rem % 2 == 1
|
||||
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
|
||||
res = fq12.Add(res, exp)
|
||||
}
|
||||
exp = fq12.Double(exp)
|
||||
rem = rem.Rsh(rem, 1) // rem = rem >> 1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Inverse returns the inverse on the Fq12
|
||||
func (fq12 Fq12) Inverse(a [2][3][2]*big.Int) [2][3][2]*big.Int {
|
||||
t0 := fq12.F.Square(a[0])
|
||||
|
||||
27
bn128/fq2.go
27
bn128/fq2.go
@@ -1,6 +1,7 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
@@ -73,6 +74,21 @@ func (fq2 Fq2) Mul(a, b [2]*big.Int) [2]*big.Int {
|
||||
fq2.F.Add(v0, v1)),
|
||||
}
|
||||
}
|
||||
func (fq2 Fq2) MulScalar(base [2]*big.Int, e *big.Int) [2]*big.Int {
|
||||
res := fq2.Zero()
|
||||
rem := e
|
||||
exp := base
|
||||
|
||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
// if rem % 2 == 1
|
||||
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
|
||||
res = fq2.Add(res, exp)
|
||||
}
|
||||
exp = fq2.Double(exp)
|
||||
rem = rem.Rsh(rem, 1) // rem = rem >> 1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Inverse returns the inverse on the Fq2
|
||||
func (fq2 Fq2) Inverse(a [2]*big.Int) [2]*big.Int {
|
||||
@@ -108,3 +124,14 @@ func (fq2 Fq2) Square(a [2]*big.Int) [2]*big.Int {
|
||||
fq2.F.Add(ab, ab),
|
||||
}
|
||||
}
|
||||
|
||||
func (fq2 Fq2) IsZero(a [2]*big.Int) bool {
|
||||
return fq2.F.IsZero(a[0]) && fq2.F.IsZero(a[1])
|
||||
}
|
||||
|
||||
func (fq2 Fq2) Affine(a [2]*big.Int) [2]*big.Int {
|
||||
return [2]*big.Int{
|
||||
fq2.F.Affine(a[0]),
|
||||
fq2.F.Affine(a[1]),
|
||||
}
|
||||
}
|
||||
|
||||
21
bn128/fq6.go
21
bn128/fq6.go
@@ -1,6 +1,7 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
@@ -42,6 +43,10 @@ func (fq6 Fq6) Add(a, b [3][2]*big.Int) [3][2]*big.Int {
|
||||
}
|
||||
}
|
||||
|
||||
func (fq6 Fq6) Double(a [3][2]*big.Int) [3][2]*big.Int {
|
||||
return fq6.Add(a, a)
|
||||
}
|
||||
|
||||
// Sub performs a substraction on the Fq6
|
||||
func (fq6 Fq6) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
|
||||
return [3][2]*big.Int{
|
||||
@@ -89,6 +94,22 @@ func (fq6 Fq6) Mul(a, b [3][2]*big.Int) [3][2]*big.Int {
|
||||
}
|
||||
}
|
||||
|
||||
func (fq6 Fq6) MulScalar(base [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
|
||||
res := fq6.Zero()
|
||||
rem := e
|
||||
exp := base
|
||||
|
||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
// if rem % 2 == 1
|
||||
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
|
||||
res = fq6.Add(res, exp)
|
||||
}
|
||||
exp = fq6.Double(exp)
|
||||
rem = rem.Rsh(rem, 1) // rem = rem >> 1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// Inverse returns the inverse on the Fq6
|
||||
func (fq6 Fq6) Inverse(a [3][2]*big.Int) [3][2]*big.Int {
|
||||
t0 := fq6.F.Square(a[0])
|
||||
|
||||
169
bn128/g1.go
Normal file
169
bn128/g1.go
Normal file
@@ -0,0 +1,169 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type G1 struct {
|
||||
F Fq
|
||||
G [3]*big.Int
|
||||
}
|
||||
|
||||
func NewG1(f Fq, g [2]*big.Int) G1 {
|
||||
var g1 G1
|
||||
g1.F = f
|
||||
g1.G = [3]*big.Int{
|
||||
g[0],
|
||||
g[1],
|
||||
g1.F.One(),
|
||||
}
|
||||
return g1
|
||||
}
|
||||
|
||||
func (g1 G1) Zero() [2]*big.Int {
|
||||
return [2]*big.Int{g1.F.Zero(), g1.F.Zero()}
|
||||
}
|
||||
func (g1 G1) IsZero(p [3]*big.Int) bool {
|
||||
return g1.F.IsZero(p[2])
|
||||
}
|
||||
|
||||
func (g1 G1) Add(p1, p2 [3]*big.Int) [3]*big.Int {
|
||||
|
||||
// https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
|
||||
// https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp#L208
|
||||
// http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
|
||||
if g1.IsZero(p1) {
|
||||
return p2
|
||||
}
|
||||
if g1.IsZero(p2) {
|
||||
return p1
|
||||
}
|
||||
|
||||
x1 := p1[0]
|
||||
y1 := p1[1]
|
||||
z1 := p1[2]
|
||||
x2 := p2[0]
|
||||
y2 := p2[1]
|
||||
z2 := p2[2]
|
||||
|
||||
z1z1 := g1.F.Square(z1)
|
||||
z2z2 := g1.F.Square(z2)
|
||||
|
||||
u1 := g1.F.Mul(x1, z2z2)
|
||||
u2 := g1.F.Mul(x2, z1z1)
|
||||
|
||||
t0 := g1.F.Mul(z2, z2z2)
|
||||
s1 := g1.F.Mul(y1, t0)
|
||||
|
||||
t1 := g1.F.Mul(z1, z1z1)
|
||||
s2 := g1.F.Mul(y2, t1)
|
||||
|
||||
h := g1.F.Sub(u2, u1)
|
||||
t2 := g1.F.Add(h, h)
|
||||
i := g1.F.Square(t2)
|
||||
j := g1.F.Mul(h, i)
|
||||
t3 := g1.F.Sub(s2, s1)
|
||||
r := g1.F.Add(t3, t3)
|
||||
v := g1.F.Mul(u1, i)
|
||||
t4 := g1.F.Square(r)
|
||||
t5 := g1.F.Add(v, v)
|
||||
t6 := g1.F.Sub(t4, j)
|
||||
x3 := g1.F.Sub(t6, t5)
|
||||
t7 := g1.F.Sub(v, x3)
|
||||
t8 := g1.F.Mul(s1, j)
|
||||
t9 := g1.F.Add(t8, t8)
|
||||
t10 := g1.F.Mul(r, t7)
|
||||
|
||||
y3 := g1.F.Sub(t10, t9)
|
||||
|
||||
t11 := g1.F.Add(z1, z2)
|
||||
t12 := g1.F.Square(t11)
|
||||
t13 := g1.F.Sub(t12, z1z1)
|
||||
t14 := g1.F.Sub(t13, z2z2)
|
||||
z3 := g1.F.Mul(t14, h)
|
||||
|
||||
return [3]*big.Int{x3, y3, z3}
|
||||
}
|
||||
|
||||
func (g1 G1) Neg(p [3]*big.Int) [3]*big.Int {
|
||||
return [3]*big.Int{
|
||||
p[0],
|
||||
g1.F.Neg(p[1]),
|
||||
p[2],
|
||||
}
|
||||
}
|
||||
func (g1 G1) Sub(a, b [3]*big.Int) [3]*big.Int {
|
||||
return g1.Add(a, g1.Neg(b))
|
||||
}
|
||||
func (g1 G1) Double(p [3]*big.Int) [3]*big.Int {
|
||||
|
||||
// https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
|
||||
// http://hyperelliptic.org/EFD/g1p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
// https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g1.cpp#L325
|
||||
|
||||
if g1.IsZero(p) {
|
||||
return p
|
||||
}
|
||||
|
||||
a := g1.F.Square(p[0])
|
||||
b := g1.F.Square(p[1])
|
||||
c := g1.F.Square(b)
|
||||
|
||||
t0 := g1.F.Add(p[0], b)
|
||||
t1 := g1.F.Square(t0)
|
||||
t2 := g1.F.Sub(t1, a)
|
||||
t3 := g1.F.Sub(t2, c)
|
||||
|
||||
d := g1.F.Double(t3)
|
||||
e := g1.F.Add(g1.F.Add(a, a), a) // e = 3*a
|
||||
f := g1.F.Square(e)
|
||||
|
||||
t4 := g1.F.Double(d)
|
||||
x3 := g1.F.Sub(f, t4)
|
||||
|
||||
t5 := g1.F.Sub(d, x3)
|
||||
twoC := g1.F.Add(c, c)
|
||||
fourC := g1.F.Add(twoC, twoC)
|
||||
t6 := g1.F.Add(fourC, fourC)
|
||||
t7 := g1.F.Mul(e, t5)
|
||||
y3 := g1.F.Sub(t7, t6)
|
||||
|
||||
t8 := g1.F.Mul(p[1], p[2])
|
||||
z3 := g1.F.Double(t8)
|
||||
|
||||
return [3]*big.Int{x3, y3, z3}
|
||||
}
|
||||
|
||||
func (g1 G1) MulScalar(base [3]*big.Int, e *big.Int) [3]*big.Int {
|
||||
// res := g1.Zero()
|
||||
res := [3]*big.Int{g1.F.Zero(), g1.F.Zero(), g1.F.Zero()}
|
||||
rem := e
|
||||
exp := base
|
||||
|
||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
// if rem % 2 == 1
|
||||
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
|
||||
res = g1.Add(res, exp)
|
||||
}
|
||||
exp = g1.Double(exp)
|
||||
rem = rem.Rsh(rem, 1) // rem = rem >> 1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (g1 G1) Affine(p [3]*big.Int) [2]*big.Int {
|
||||
if g1.IsZero(p) {
|
||||
return g1.Zero()
|
||||
}
|
||||
|
||||
zinv := g1.F.Inverse(p[2])
|
||||
zinv2 := g1.F.Square(zinv)
|
||||
x := g1.F.Mul(p[0], zinv2)
|
||||
|
||||
zinv3 := g1.F.Mul(zinv2, zinv)
|
||||
y := g1.F.Mul(p[1], zinv3)
|
||||
|
||||
return [2]*big.Int{x, y}
|
||||
}
|
||||
30
bn128/g1_test.go
Normal file
30
bn128/g1_test.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/arnaucube/cryptofun/utils"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestG1(t *testing.T) {
|
||||
bn128, err := NewBn128()
|
||||
assert.Nil(t, err)
|
||||
|
||||
r1 := big.NewInt(int64(33))
|
||||
r2 := big.NewInt(int64(44))
|
||||
|
||||
gr1 := bn128.G1.MulScalar(bn128.G1.G, bn128.Fq1.Copy(r1))
|
||||
gr2 := bn128.G1.MulScalar(bn128.G1.G, bn128.Fq1.Copy(r2))
|
||||
|
||||
grsum1 := bn128.G1.Add(gr1, gr2)
|
||||
r1r2 := bn128.Fq1.Add(r1, r2)
|
||||
grsum2 := bn128.G1.MulScalar(bn128.G1.G, r1r2)
|
||||
|
||||
a := bn128.G1.Affine(grsum1)
|
||||
b := bn128.G1.Affine(grsum2)
|
||||
assert.Equal(t, a, b)
|
||||
assert.Equal(t, "0x2f978c0ab89ebaa576866706b14787f360c4d6c3869efe5a72f7c3651a72ff00", utils.BytesToHex(a[0].Bytes()))
|
||||
assert.Equal(t, "0x12e4ba7f0edca8b4fa668fe153aebd908d322dc26ad964d4cd314795844b62b2", utils.BytesToHex(a[1].Bytes()))
|
||||
}
|
||||
174
bn128/g2.go
Normal file
174
bn128/g2.go
Normal file
@@ -0,0 +1,174 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
)
|
||||
|
||||
type G2 struct {
|
||||
F Fq2
|
||||
G [3][2]*big.Int
|
||||
}
|
||||
|
||||
func NewG2(f Fq2, g [2][2]*big.Int) G2 {
|
||||
var g2 G2
|
||||
g2.F = f
|
||||
g2.G = [3][2]*big.Int{
|
||||
g[0],
|
||||
g[1],
|
||||
g2.F.One(),
|
||||
}
|
||||
return g2
|
||||
}
|
||||
|
||||
func (g2 G2) Zero() [2][2]*big.Int {
|
||||
return [2][2]*big.Int{g2.F.Zero(), g2.F.Zero()}
|
||||
}
|
||||
func (g2 G2) IsZero(p [3][2]*big.Int) bool {
|
||||
return g2.F.IsZero(p[2])
|
||||
}
|
||||
|
||||
func (g2 G2) Add(p1, p2 [3][2]*big.Int) [3][2]*big.Int {
|
||||
|
||||
// https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
|
||||
// https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp#L208
|
||||
// http://hyperelliptic.org/EFD/g2p/auto-code/shortw/jacobian-0/addition/add-2007-bl.op3
|
||||
|
||||
if g2.IsZero(p1) {
|
||||
return p2
|
||||
}
|
||||
if g2.IsZero(p2) {
|
||||
return p1
|
||||
}
|
||||
|
||||
x1 := p1[0]
|
||||
y1 := p1[1]
|
||||
z1 := p1[2]
|
||||
x2 := p2[0]
|
||||
y2 := p2[1]
|
||||
z2 := p2[2]
|
||||
|
||||
z1z1 := g2.F.Square(z1)
|
||||
z2z2 := g2.F.Square(z2)
|
||||
|
||||
u1 := g2.F.Mul(x1, z2z2)
|
||||
u2 := g2.F.Mul(x2, z1z1)
|
||||
|
||||
t0 := g2.F.Mul(z2, z2z2)
|
||||
s1 := g2.F.Mul(y1, t0)
|
||||
|
||||
t1 := g2.F.Mul(z1, z1z1)
|
||||
s2 := g2.F.Mul(y2, t1)
|
||||
|
||||
h := g2.F.Sub(u2, u1)
|
||||
t2 := g2.F.Add(h, h)
|
||||
i := g2.F.Square(t2)
|
||||
j := g2.F.Mul(h, i)
|
||||
t3 := g2.F.Sub(s2, s1)
|
||||
r := g2.F.Add(t3, t3)
|
||||
v := g2.F.Mul(u1, i)
|
||||
t4 := g2.F.Square(r)
|
||||
t5 := g2.F.Add(v, v)
|
||||
t6 := g2.F.Sub(t4, j)
|
||||
x3 := g2.F.Sub(t6, t5)
|
||||
t7 := g2.F.Sub(v, x3)
|
||||
t8 := g2.F.Mul(s1, j)
|
||||
t9 := g2.F.Add(t8, t8)
|
||||
t10 := g2.F.Mul(r, t7)
|
||||
|
||||
y3 := g2.F.Sub(t10, t9)
|
||||
|
||||
t11 := g2.F.Add(z1, z2)
|
||||
t12 := g2.F.Square(t11)
|
||||
t13 := g2.F.Sub(t12, z1z1)
|
||||
t14 := g2.F.Sub(t13, z2z2)
|
||||
z3 := g2.F.Mul(t14, h)
|
||||
|
||||
return [3][2]*big.Int{x3, y3, z3}
|
||||
}
|
||||
|
||||
func (g2 G2) Neg(p [3][2]*big.Int) [3][2]*big.Int {
|
||||
return [3][2]*big.Int{
|
||||
p[0],
|
||||
g2.F.Neg(p[1]),
|
||||
p[2],
|
||||
}
|
||||
}
|
||||
|
||||
func (g2 G2) Sub(a, b [3][2]*big.Int) [3][2]*big.Int {
|
||||
return g2.Add(a, g2.Neg(b))
|
||||
}
|
||||
|
||||
func (g2 G2) Double(p [3][2]*big.Int) [3][2]*big.Int {
|
||||
|
||||
// https://en.wikibooks.org/wiki/Cryptography/Prime_Curve/Jacobian_Coordinates
|
||||
// http://hyperelliptic.org/EFD/g2p/auto-code/shortw/jacobian-0/doubling/dbl-2009-l.op3
|
||||
// https://github.com/zcash/zcash/blob/master/src/snark/libsnark/algebra/curves/alt_bn128/alt_bn128_g2.cpp#L325
|
||||
|
||||
if g2.IsZero(p) {
|
||||
return p
|
||||
}
|
||||
|
||||
a := g2.F.Square(p[0])
|
||||
b := g2.F.Square(p[1])
|
||||
c := g2.F.Square(b)
|
||||
|
||||
t0 := g2.F.Add(p[0], b)
|
||||
t1 := g2.F.Square(t0)
|
||||
t2 := g2.F.Sub(t1, a)
|
||||
t3 := g2.F.Sub(t2, c)
|
||||
|
||||
d := g2.F.Double(t3)
|
||||
e := g2.F.Add(g2.F.Add(a, a), a) // e = 3*a
|
||||
f := g2.F.Square(e)
|
||||
|
||||
t4 := g2.F.Double(d)
|
||||
x3 := g2.F.Sub(f, t4)
|
||||
|
||||
t5 := g2.F.Sub(d, x3)
|
||||
twoC := g2.F.Add(c, c)
|
||||
fourC := g2.F.Add(twoC, twoC)
|
||||
t6 := g2.F.Add(fourC, fourC)
|
||||
t7 := g2.F.Mul(e, t5)
|
||||
y3 := g2.F.Sub(t7, t6)
|
||||
|
||||
t8 := g2.F.Mul(p[1], p[2])
|
||||
z3 := g2.F.Double(t8)
|
||||
|
||||
return [3][2]*big.Int{x3, y3, z3}
|
||||
}
|
||||
|
||||
func (g2 G2) MulScalar(base [3][2]*big.Int, e *big.Int) [3][2]*big.Int {
|
||||
// res := g2.Zero()
|
||||
res := [3][2]*big.Int{g2.F.Zero(), g2.F.Zero(), g2.F.Zero()}
|
||||
rem := e
|
||||
exp := base
|
||||
|
||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
// if rem % 2 == 1
|
||||
if bytes.Equal(new(big.Int).Rem(rem, big.NewInt(int64(2))).Bytes(), big.NewInt(int64(1)).Bytes()) {
|
||||
res = g2.Add(res, exp)
|
||||
}
|
||||
exp = g2.Double(exp)
|
||||
rem = rem.Rsh(rem, 1) // rem = rem >> 1
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
func (g2 G2) Affine(p [3][2]*big.Int) [2][2]*big.Int {
|
||||
if g2.IsZero(p) {
|
||||
return g2.Zero()
|
||||
}
|
||||
|
||||
zinv := g2.F.Inverse(p[2])
|
||||
zinv2 := g2.F.Square(zinv)
|
||||
x := g2.F.Mul(p[0], zinv2)
|
||||
|
||||
zinv3 := g2.F.Mul(zinv2, zinv)
|
||||
y := g2.F.Mul(p[1], zinv3)
|
||||
|
||||
return [2][2]*big.Int{
|
||||
x,
|
||||
y,
|
||||
}
|
||||
}
|
||||
27
bn128/g2_test.go
Normal file
27
bn128/g2_test.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package bn128
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestG2(t *testing.T) {
|
||||
bn128, err := NewBn128()
|
||||
assert.Nil(t, err)
|
||||
|
||||
r1 := big.NewInt(int64(33))
|
||||
r2 := big.NewInt(int64(44))
|
||||
|
||||
gr1 := bn128.G2.MulScalar(bn128.G2.G, bn128.Fq1.Copy(r1))
|
||||
gr2 := bn128.G2.MulScalar(bn128.G2.G, bn128.Fq1.Copy(r2))
|
||||
|
||||
grsum1 := bn128.G2.Add(gr1, gr2)
|
||||
r1r2 := bn128.Fq1.Add(r1, r2)
|
||||
grsum2 := bn128.G2.MulScalar(bn128.G2.G, r1r2)
|
||||
|
||||
a := bn128.G2.Affine(grsum1)
|
||||
b := bn128.G2.Affine(grsum2)
|
||||
assert.Equal(t, a, b)
|
||||
}
|
||||
Reference in New Issue
Block a user