mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 02:42:27 +00:00
2238 lines
47 KiB
Go
2238 lines
47 KiB
Go
package bls12381
|
|
|
|
import (
|
|
"bytes"
|
|
"crypto/rand"
|
|
"math/big"
|
|
"testing"
|
|
)
|
|
|
|
func TestFpSerialization(t *testing.T) {
|
|
t.Run("zero", func(t *testing.T) {
|
|
in := make([]byte, fpByteSize)
|
|
fe, err := fromBytes(in)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !fe.isZero() {
|
|
t.Fatal("serialization failed")
|
|
}
|
|
if !bytes.Equal(in, toBytes(fe)) {
|
|
t.Fatal("serialization failed")
|
|
}
|
|
})
|
|
t.Run("bytes", func(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, err := fromBytes(toBytes(a))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !a.equal(b) {
|
|
t.Fatal("serialization failed")
|
|
}
|
|
}
|
|
})
|
|
t.Run("string", func(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, err := fromString(toString(a))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !a.equal(b) {
|
|
t.Fatal("encoding or decoding failed")
|
|
}
|
|
}
|
|
})
|
|
t.Run("big", func(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, err := fromBig(toBig(a))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !a.equal(b) {
|
|
t.Fatal("encoding or decoding failed")
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
func TestFpAdditionCrossAgainstBigInt(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
c := new(fe)
|
|
big_a := a.big()
|
|
big_b := b.big()
|
|
big_c := new(big.Int)
|
|
add(c, a, b)
|
|
out_1 := c.bytes()
|
|
out_2 := padBytes(big_c.Add(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed A")
|
|
}
|
|
double(c, a)
|
|
out_1 = c.bytes()
|
|
out_2 = padBytes(big_c.Add(big_a, big_a).Mod(big_c, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed B")
|
|
}
|
|
sub(c, a, b)
|
|
out_1 = c.bytes()
|
|
out_2 = padBytes(big_c.Sub(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed C")
|
|
}
|
|
neg(c, a)
|
|
out_1 = c.bytes()
|
|
out_2 = padBytes(big_c.Neg(big_a).Mod(big_c, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed D")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpAdditionCrossAgainstBigIntAssigned(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
big_a, big_b := a.big(), b.big()
|
|
addAssign(a, b)
|
|
out_1 := a.bytes()
|
|
out_2 := padBytes(big_a.Add(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed A")
|
|
}
|
|
a, _ = new(fe).rand(rand.Reader)
|
|
big_a = a.big()
|
|
doubleAssign(a)
|
|
out_1 = a.bytes()
|
|
out_2 = padBytes(big_a.Add(big_a, big_a).Mod(big_a, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed B")
|
|
}
|
|
a, _ = new(fe).rand(rand.Reader)
|
|
b, _ = new(fe).rand(rand.Reader)
|
|
big_a, big_b = a.big(), b.big()
|
|
subAssign(a, b)
|
|
out_1 = a.bytes()
|
|
out_2 = padBytes(big_a.Sub(big_a, big_b).Mod(big_a, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed A")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpAdditionProperties(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
|
|
zero := new(fe).zero()
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
c1, c2 := new(fe), new(fe)
|
|
add(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
sub(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
double(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
neg(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("-0 == 0")
|
|
}
|
|
sub(c1, zero, a)
|
|
neg(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
double(c1, a)
|
|
add(c2, a, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
add(c1, a, b)
|
|
add(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
sub(c1, a, b)
|
|
sub(c2, b, a)
|
|
neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
cx, _ := new(fe).rand(rand.Reader)
|
|
add(c1, a, b)
|
|
add(c1, c1, cx)
|
|
add(c2, a, cx)
|
|
add(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a + b) + c == (a + c ) + b")
|
|
}
|
|
sub(c1, a, b)
|
|
sub(c1, c1, cx)
|
|
sub(c2, a, cx)
|
|
sub(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a - b) - c == (a - c ) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpAdditionPropertiesAssigned(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
zero := new(fe).zero()
|
|
a, b := new(fe), new(fe)
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
addAssign(a, zero)
|
|
if !a.equal(b) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
subAssign(a, zero)
|
|
if !a.equal(b) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
a.set(zero)
|
|
doubleAssign(a)
|
|
if !a.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
a.set(zero)
|
|
subAssign(a, b)
|
|
neg(b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
doubleAssign(a)
|
|
addAssign(b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c1, c2 := new(fe).set(a), new(fe).set(b)
|
|
addAssign(c1, b)
|
|
addAssign(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c1.set(a)
|
|
c2.set(b)
|
|
subAssign(c1, b)
|
|
subAssign(c2, a)
|
|
neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c, _ := new(fe).rand(rand.Reader)
|
|
a0 := new(fe).set(a)
|
|
addAssign(a, b)
|
|
addAssign(a, c)
|
|
addAssign(b, c)
|
|
addAssign(b, a0)
|
|
if !a.equal(b) {
|
|
t.Fatal("(a + b) + c == (b + c) + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
_, _ = c.rand(rand.Reader)
|
|
a0.set(a)
|
|
subAssign(a, b)
|
|
subAssign(a, c)
|
|
subAssign(a0, c)
|
|
subAssign(a0, b)
|
|
if !a.equal(a0) {
|
|
t.Fatal("(a - b) - c == (a - c) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpLazyOperations(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
c, _ := new(fe).rand(rand.Reader)
|
|
c0 := new(fe)
|
|
c1 := new(fe)
|
|
ladd(c0, a, b)
|
|
add(c1, a, b)
|
|
mul(c0, c0, c)
|
|
mul(c1, c1, c)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("(a + b) * c == (a l+ b) * c")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
ldouble(a, a)
|
|
ladd(b, b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("2 l* a = a l+ a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
_, _ = c.rand(rand.Reader)
|
|
a0 := new(fe).set(a)
|
|
lsubAssign(a, b)
|
|
laddAssign(a, &modulus)
|
|
mul(a, a, c)
|
|
subAssign(a0, b)
|
|
mul(a0, a0, c)
|
|
if !a.equal(a0) {
|
|
t.Fatal("((a l- b) + p) * c = (a-b) * c")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpMultiplicationCrossAgainstBigInt(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
c := new(fe)
|
|
big_a := toBig(a)
|
|
big_b := toBig(b)
|
|
big_c := new(big.Int)
|
|
mul(c, a, b)
|
|
out_1 := toBytes(c)
|
|
out_2 := padBytes(big_c.Mul(big_a, big_b).Mod(big_c, modulus.big()).Bytes(), fpByteSize)
|
|
if !bytes.Equal(out_1, out_2) {
|
|
t.Fatal("cross test against big.Int is failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpMultiplicationProperties(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
zero, one := new(fe).zero(), new(fe).one()
|
|
c1, c2 := new(fe), new(fe)
|
|
mul(c1, a, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
mul(c1, a, one)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
mul(c1, a, b)
|
|
mul(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
cx, _ := new(fe).rand(rand.Reader)
|
|
mul(c1, a, b)
|
|
mul(c1, c1, cx)
|
|
mul(c2, cx, b)
|
|
mul(c2, c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
square(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("0^2 == 0")
|
|
}
|
|
square(a, one)
|
|
if !a.equal(one) {
|
|
t.Fatal("1^2 == 1")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
square(c1, a)
|
|
mul(c2, a, a)
|
|
if !c1.equal(c1) {
|
|
t.Fatal("a^2 == a*a")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpExponentiation(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
u := new(fe)
|
|
exp(u, a, big.NewInt(0))
|
|
if !u.isOne() {
|
|
t.Fatal("a^0 == 1")
|
|
}
|
|
exp(u, a, big.NewInt(1))
|
|
if !u.equal(a) {
|
|
t.Fatal("a^1 == a")
|
|
}
|
|
v := new(fe)
|
|
mul(u, a, a)
|
|
mul(u, u, u)
|
|
mul(u, u, u)
|
|
exp(v, a, big.NewInt(8))
|
|
if !u.equal(v) {
|
|
t.Fatal("((a^2)^2)^2 == a^8")
|
|
}
|
|
p := modulus.big()
|
|
exp(u, a, p)
|
|
if !u.equal(a) {
|
|
t.Fatal("a^p == a")
|
|
}
|
|
exp(u, a, p.Sub(p, big.NewInt(1)))
|
|
if !u.isOne() {
|
|
t.Fatal("a^(p-1) == 1")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpInversion(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
u := new(fe)
|
|
zero, one := new(fe).zero(), new(fe).one()
|
|
inverse(u, zero)
|
|
if !u.equal(zero) {
|
|
t.Fatal("(0^-1) == 0)")
|
|
}
|
|
inverse(u, one)
|
|
if !u.equal(one) {
|
|
t.Fatal("(1^-1) == 1)")
|
|
}
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
inverse(u, a)
|
|
mul(u, u, a)
|
|
if !u.equal(one) {
|
|
t.Fatal("(r*a) * r*(a^-1) == r)")
|
|
}
|
|
v := new(fe)
|
|
p := modulus.big()
|
|
exp(u, a, p.Sub(p, big.NewInt(2)))
|
|
inverse(v, a)
|
|
if !v.equal(u) {
|
|
t.Fatal("a^(p-2) == a^-1")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpBatchInversion(t *testing.T) {
|
|
n := 20
|
|
for i := 0; i < n; i++ {
|
|
e0 := make([]fe, n)
|
|
e1 := make([]fe, n)
|
|
for j := 0; j < n; j++ {
|
|
if j != i {
|
|
e, err := new(fe).rand(rand.Reader)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
e0[j].set(e)
|
|
}
|
|
inverse(&e1[j], &e0[j])
|
|
}
|
|
|
|
inverseBatch(e0)
|
|
for j := 0; j < n; j++ {
|
|
if !e0[j].equal(&e1[j]) {
|
|
t.Fatal("batch inversion failed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpSquareRoot(t *testing.T) {
|
|
if sqrt(new(fe), nonResidue1) {
|
|
t.Fatal("non residue cannot have a sqrt")
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
r0, r1 := new(fe), new(fe)
|
|
d0 := sqrt(r0, a)
|
|
d1 := _sqrt(r1, a)
|
|
if d0 != d1 {
|
|
t.Fatal("sqrt decision failed")
|
|
}
|
|
if d0 {
|
|
square(r0, r0)
|
|
square(r1, r1)
|
|
if !r0.equal(r1) {
|
|
t.Fatal("sqrt failed")
|
|
}
|
|
if !r0.equal(a) {
|
|
t.Fatal("sqrt failed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFpNonResidue(t *testing.T) {
|
|
if !isQuadraticNonResidue(nonResidue1) {
|
|
t.Fatal("element is quadratic non residue, 1")
|
|
}
|
|
if isQuadraticNonResidue(new(fe).one()) {
|
|
t.Fatal("one is not quadratic non residue")
|
|
}
|
|
if !isQuadraticNonResidue(new(fe).zero()) {
|
|
t.Fatal("should accept zero as quadratic non residue")
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
square(a, a)
|
|
if isQuadraticNonResidue(a) {
|
|
t.Fatal("element is not quadratic non residue")
|
|
}
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
if !sqrt(new(fe), a) {
|
|
if !isQuadraticNonResidue(a) {
|
|
t.Fatal("element is quadratic non residue, 2", i)
|
|
}
|
|
} else {
|
|
i -= 1
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWFp(t *testing.T) {
|
|
w := new(wfe)
|
|
a := new(fe)
|
|
fromWide(a, w)
|
|
if !a.isZero() {
|
|
t.Fatal("expect zero")
|
|
}
|
|
w[0] = r1[0]
|
|
w[1] = r1[1]
|
|
w[2] = r1[2]
|
|
w[3] = r1[3]
|
|
w[4] = r1[4]
|
|
w[5] = r1[5]
|
|
fromWide(a, w)
|
|
if !(a[0] == 1 && a[1] == 0 && a[2] == 0 && a[3] == 0 && a[4] == 0 && a[5] == 0) {
|
|
t.Fatal("expect one")
|
|
}
|
|
}
|
|
|
|
func TestWFpAddition(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
w0, w1 := new(wfe), new(wfe)
|
|
c0, c1 := new(fe), new(fe)
|
|
|
|
wmul(w0, a, b)
|
|
w1.set(w0)
|
|
wadd(w0, w0, w0)
|
|
wadd(w0, w0, w0)
|
|
wadd(w0, w0, w0)
|
|
lwadd(w1, w1, w1)
|
|
lwadd(w1, w1, w1)
|
|
lwadd(w1, w1, w1)
|
|
fromWide(c0, w0)
|
|
fromWide(c1, w1)
|
|
|
|
if !c1.equal(c0) {
|
|
t.Fatal("addition failed")
|
|
}
|
|
|
|
wmul(w0, a, b)
|
|
w1.set(w0)
|
|
wdouble(w0, w0)
|
|
wdouble(w0, w0)
|
|
wdouble(w0, w0)
|
|
lwdouble(w1, w1)
|
|
lwdouble(w1, w1)
|
|
lwdouble(w1, w1)
|
|
fromWide(c0, w0)
|
|
fromWide(c1, w1)
|
|
|
|
if !c1.equal(c0) {
|
|
t.Fatal("doubling failed")
|
|
}
|
|
|
|
wmul(w0, a, &fe{10001})
|
|
wmul(w1, a, &fe{10000})
|
|
w2 := new(wfe)
|
|
wsub(w2, w0, w1)
|
|
lwsub(w0, w0, w1)
|
|
fromWide(c0, w2)
|
|
fromWide(c1, w0)
|
|
|
|
fromMont(a, a)
|
|
if !c1.equal(a) {
|
|
t.Fatal("subtraction failed")
|
|
}
|
|
if !c0.equal(a) {
|
|
t.Fatal("subtraction failed")
|
|
}
|
|
|
|
wmul(w0, a, &fe{10001})
|
|
wmul(w1, a, &fe{10000})
|
|
wsub(w0, w1, w0)
|
|
fromWide(c0, w0)
|
|
|
|
neg(a, a)
|
|
fromMont(a, a)
|
|
if !c0.equal(a) {
|
|
t.Fatal("subtraction failed")
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func TestWFpMultiplication(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
a0, _ := new(fe).rand(rand.Reader)
|
|
b0, _ := new(fe).rand(rand.Reader)
|
|
a1, _ := new(fe).rand(rand.Reader)
|
|
b1, _ := new(fe).rand(rand.Reader)
|
|
w0, w1, w2, w3 := new(wfe), new(wfe), new(wfe), new(wfe)
|
|
c0, c1 := new(fe), new(fe)
|
|
r0, r1 := new(fe), new(fe)
|
|
|
|
wmul(w0, a0, b0)
|
|
fromWide(r0, w0)
|
|
mul(r1, a0, b0)
|
|
|
|
if !r1.equal(r0) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
|
|
wmul(w0, a0, b0)
|
|
wmul(w1, a1, b1)
|
|
lwadd(w0, w0, w1)
|
|
fromWide(r0, w0)
|
|
|
|
mul(c0, a0, b0)
|
|
mul(c1, a1, b1)
|
|
add(r1, c0, c1)
|
|
|
|
if !r1.equal(r0) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
|
|
wmul(w0, a0, b0)
|
|
wmul(w1, a0, b1)
|
|
wmul(w2, a1, b0)
|
|
wmul(w3, a1, b1)
|
|
lwadd(w0, w0, w1)
|
|
lwadd(w0, w0, w2)
|
|
lwadd(w0, w0, w3)
|
|
fromWide(r0, w0)
|
|
|
|
add(c0, a0, a1)
|
|
add(c1, b0, b1)
|
|
mul(r1, c0, c1)
|
|
|
|
if !r1.equal(r0) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2Serialization(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
b, err := f.fromBytes(f.toBytes(a))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !a.equal(b) {
|
|
t.Fatal("serialization failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2AdditionProperties(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
zero := f.zero()
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
b, _ := new(fe2).rand(rand.Reader)
|
|
c1 := f.new()
|
|
c2 := f.new()
|
|
fp2Add(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
fp2Sub(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
fp2Double(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
fp2Neg(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("-0 == 0")
|
|
}
|
|
fp2Sub(c1, zero, a)
|
|
fp2Neg(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
fp2Double(c1, a)
|
|
fp2Add(c2, a, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
fp2Add(c1, a, b)
|
|
fp2Add(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
fp2Sub(c1, a, b)
|
|
fp2Sub(c2, b, a)
|
|
fp2Neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
cx, _ := new(fe2).rand(rand.Reader)
|
|
fp2Add(c1, a, b)
|
|
fp2Add(c1, c1, cx)
|
|
fp2Add(c2, a, cx)
|
|
fp2Add(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a + b) + c == (a + c ) + b")
|
|
}
|
|
fp2Sub(c1, a, b)
|
|
fp2Sub(c1, c1, cx)
|
|
fp2Sub(c2, a, cx)
|
|
fp2Sub(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a - b) - c == (a - c ) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2AdditionPropertiesAssigned(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
zero := new(fe2).zero()
|
|
a, b := new(fe2), new(fe2)
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
fp2AddAssign(a, zero)
|
|
if !a.equal(b) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
fp2SubAssign(a, zero)
|
|
if !a.equal(b) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
a.set(zero)
|
|
fp2DoubleAssign(a)
|
|
if !a.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
a.set(zero)
|
|
fp2SubAssign(a, b)
|
|
fp2Neg(b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
fp2DoubleAssign(a)
|
|
fp2AddAssign(b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c1, c2 := new(fe2).set(a), new(fe2).set(b)
|
|
fp2AddAssign(c1, b)
|
|
fp2AddAssign(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c1.set(a)
|
|
c2.set(b)
|
|
fp2SubAssign(c1, b)
|
|
fp2SubAssign(c2, a)
|
|
fp2Neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c, _ := new(fe2).rand(rand.Reader)
|
|
a0 := new(fe2).set(a)
|
|
fp2AddAssign(a, b)
|
|
fp2AddAssign(a, c)
|
|
fp2AddAssign(b, c)
|
|
fp2AddAssign(b, a0)
|
|
if !a.equal(b) {
|
|
t.Fatal("(a + b) + c == (b + c) + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
_, _ = c.rand(rand.Reader)
|
|
a0.set(a)
|
|
fp2SubAssign(a, b)
|
|
fp2SubAssign(a, c)
|
|
fp2SubAssign(a0, c)
|
|
fp2SubAssign(a0, b)
|
|
if !a.equal(a0) {
|
|
t.Fatal("(a - b) - c == (a - c) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2LazyOperations(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
b, _ := new(fe2).rand(rand.Reader)
|
|
c, _ := new(fe2).rand(rand.Reader)
|
|
c0 := new(fe2)
|
|
c1 := new(fe2)
|
|
fp2Ladd(c0, a, b)
|
|
fp2Add(c1, a, b)
|
|
fp2LaddAssign(a, b)
|
|
f.mulAssign(c0, c)
|
|
f.mulAssign(c1, c)
|
|
f.mulAssign(a, c)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("(a + b) * c == (a l+ b) * c")
|
|
}
|
|
if !c0.equal(c1) {
|
|
t.Fatal("(a + b) * c == (a l+ b) * c")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2MulByNonResidue(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
r0, r1, r2, r3 := new(fe2), new(fe2), new(fe2), new(fe2)
|
|
f.mul(r1, a, nonResidue2)
|
|
mulByNonResidue(r0, a)
|
|
r2.set(a)
|
|
mulByNonResidueAssign(r2)
|
|
_fp2MulByNonResidue(r3, a)
|
|
|
|
if !r0.equal(r1) {
|
|
t.Fatal("mul by non residue failed")
|
|
}
|
|
if !r0.equal(r2) {
|
|
t.Fatal("mul by non residue failed")
|
|
}
|
|
if !r0.equal(r3) {
|
|
t.Fatal("mul by non residue failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2MultiplicationProperties(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
b, _ := new(fe2).rand(rand.Reader)
|
|
zero := f.zero()
|
|
one := f.one()
|
|
c1, c2 := f.new(), f.new()
|
|
f.mul(c1, a, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
f.mul(c1, a, one)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
f.mul(c1, a, b)
|
|
f.mul(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
cx, _ := new(fe2).rand(rand.Reader)
|
|
f.mul(c1, a, b)
|
|
f.mul(c1, c1, cx)
|
|
f.mul(c2, cx, b)
|
|
f.mul(c2, c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
f.square(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("0^2 == 0")
|
|
}
|
|
f.square(a, one)
|
|
if !a.equal(one) {
|
|
t.Fatal("1^2 == 1")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
f.square(c1, a)
|
|
f.mul(c2, a, a)
|
|
if !c2.equal(c1) {
|
|
t.Fatal("a^2 == a*a")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2MultiplicationPropertiesAssigned(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
zero, one := new(fe2).zero(), new(fe2).one()
|
|
f.mulAssign(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
a0 := new(fe2).set(a)
|
|
f.mulAssign(a, one)
|
|
if !a.equal(a0) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b, _ := new(fe2).rand(rand.Reader)
|
|
a0.set(a)
|
|
f.mulAssign(a, b)
|
|
f.mulAssign(b, a0)
|
|
if !a.equal(b) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
c, _ := new(fe2).rand(rand.Reader)
|
|
a0.set(a)
|
|
f.mulAssign(a, b)
|
|
f.mulAssign(a, c)
|
|
f.mulAssign(a0, c)
|
|
f.mulAssign(a0, b)
|
|
if !a.equal(a0) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
a0.set(a)
|
|
f.squareAssign(a)
|
|
f.mulAssign(a0, a0)
|
|
if !a.equal(a0) {
|
|
t.Fatal("a^2 == a*a")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2Exponentiation(t *testing.T) {
|
|
f := newFp2()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
u := f.new()
|
|
f.exp(u, a, big.NewInt(0))
|
|
if !u.equal(f.one()) {
|
|
t.Fatal("a^0 == 1")
|
|
}
|
|
f.exp(u, a, big.NewInt(1))
|
|
if !u.equal(a) {
|
|
t.Fatal("a^1 == a")
|
|
}
|
|
v := f.new()
|
|
f.mul(u, a, a)
|
|
f.mul(u, u, u)
|
|
f.mul(u, u, u)
|
|
f.exp(v, a, big.NewInt(8))
|
|
if !u.equal(v) {
|
|
t.Fatal("((a^2)^2)^2 == a^8")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2Inversion(t *testing.T) {
|
|
f := newFp2()
|
|
u := f.new()
|
|
zero := f.zero()
|
|
one := f.one()
|
|
f.inverse(u, zero)
|
|
if !u.equal(zero) {
|
|
t.Fatal("(0 ^ -1) == 0)")
|
|
}
|
|
f.inverse(u, one)
|
|
if !u.equal(one) {
|
|
t.Fatal("(1 ^ -1) == 1)")
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
f.inverse(u, a)
|
|
f.mul(u, u, a)
|
|
if !u.equal(one) {
|
|
t.Fatal("(r * a) * r * (a ^ -1) == r)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2BatchInversion(t *testing.T) {
|
|
f := newFp2()
|
|
n := 20
|
|
for i := 0; i < n; i++ {
|
|
e0 := make([]fe2, n)
|
|
e1 := make([]fe2, n)
|
|
for j := 0; j < n; j++ {
|
|
if j != i {
|
|
e, err := new(fe2).rand(rand.Reader)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
e0[j].set(e)
|
|
}
|
|
f.inverse(&e1[j], &e0[j])
|
|
}
|
|
f.inverseBatch(e0)
|
|
for j := 0; j < n; j++ {
|
|
if !e0[j].equal(&e1[j]) {
|
|
t.Fatal("batch inversion failed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2SquareRoot(t *testing.T) {
|
|
e := newFp2()
|
|
if e.sqrtBLST(e.new(), nonResidue2) {
|
|
t.Fatal("non residue cannot have a sqrt")
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
r0, r1 := new(fe2), new(fe2)
|
|
d0 := e.sqrt(r0, a)
|
|
d1 := e.sqrtBLST(r1, a)
|
|
if d0 != d1 {
|
|
t.Fatal("sqrt decision failed")
|
|
}
|
|
if d0 {
|
|
e.square(r0, r0)
|
|
e.square(r1, r1)
|
|
if !r0.equal(r1) {
|
|
t.Fatal("sqrt failed")
|
|
}
|
|
if !r0.equal(a) {
|
|
t.Fatal("sqrt failed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2NonResidue(t *testing.T) {
|
|
f := newFp2()
|
|
if !f.isQuadraticNonResidue(nonResidue2) {
|
|
t.Fatal("element is quadratic non residue, 1")
|
|
}
|
|
if f.isQuadraticNonResidue(new(fe2).one()) {
|
|
t.Fatal("one is not quadratic non residue")
|
|
}
|
|
if !f.isQuadraticNonResidue(new(fe2).zero()) {
|
|
t.Fatal("should accept zero as quadratic non residue")
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
f.squareAssign(a)
|
|
if f.isQuadraticNonResidue(a) {
|
|
t.Fatal("element is not quadratic non residue")
|
|
}
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
if !f.sqrt(new(fe2), a) {
|
|
if !f.isQuadraticNonResidue(a) {
|
|
t.Fatal("element is quadratic non residue, 2", i)
|
|
}
|
|
} else {
|
|
i -= 1
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWFp2Addition(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
r0, _ := new(fe2).rand(rand.Reader)
|
|
r1, _ := new(fe2).rand(rand.Reader)
|
|
r2, _ := new(fe2).rand(rand.Reader)
|
|
rw0, rw1, w0, w1 := new(wfe2), new(wfe2), new(wfe2), new(wfe2)
|
|
|
|
wfp2Mul(w0, r0, r1)
|
|
wfp2Mul(w1, r0, r2)
|
|
|
|
_wfp2Add(rw0, w0, w1)
|
|
wfp2Add(rw1, w0, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("add failed")
|
|
}
|
|
rw1.set(w0)
|
|
wfp2AddAssign(rw1, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("assigned add failed")
|
|
}
|
|
|
|
_wfp2AddMixed(rw0, w0, w1)
|
|
wfp2AddMixed(rw1, w0, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("add mixed failed")
|
|
}
|
|
rw1.set(w0)
|
|
wfp2AddMixedAssign(rw1, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("assigned mixed add failed")
|
|
}
|
|
|
|
_wfp2Ladd(rw0, w0, w1)
|
|
wfp2Ladd(rw1, w0, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("lazy add failed")
|
|
}
|
|
rw1.set(w0)
|
|
wfp2LaddAssign(rw1, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("assigned lazy add failed")
|
|
}
|
|
|
|
_wfp2Sub(rw0, w0, w1)
|
|
wfp2Sub(rw1, w0, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("sub failed")
|
|
}
|
|
rw1.set(w0)
|
|
wfp2SubAssign(rw1, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("assigned sub failed")
|
|
}
|
|
|
|
_wfp2SubMixed(rw0, w0, w1)
|
|
wfp2SubMixed(rw1, w0, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("sub mixed failed")
|
|
}
|
|
rw1.set(w0)
|
|
wfp2SubMixedAssign(rw1, w1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("assigned sub mixed failed")
|
|
}
|
|
|
|
_wfp2Double(rw0, w0)
|
|
wfp2Double(rw1, w0)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("doubling failed")
|
|
}
|
|
rw1.set(w0)
|
|
wfp2DoubleAssign(rw1)
|
|
if !rw0.equal(rw1) {
|
|
t.Fatal("assigned doubling failed")
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func TestFp2MultiplicationCross(t *testing.T) {
|
|
f := newFp2()
|
|
a, b, c0, c1 := new(fe2), new(fe2), new(fe2), new(fe2)
|
|
w0, w1 := new(wfe2), new(wfe2)
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
_wfp2Mul(w0, a, b)
|
|
wfp2Mul(w1, a, b)
|
|
if !w0.equal(w1) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
c0.fromWide(w0)
|
|
f.mul(c1, a, b)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp2SquareCross(t *testing.T) {
|
|
f := newFp2()
|
|
a, c0, c1 := new(fe2), new(fe2), new(fe2)
|
|
w0, w1 := new(wfe2), new(wfe2)
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a.rand(rand.Reader)
|
|
_wfp2Square(w0, a)
|
|
wfp2Square(w1, a)
|
|
if !w0.equal(w1) {
|
|
t.Fatal("squaring failed")
|
|
}
|
|
c0.fromWide(w0)
|
|
f.square(c1, a)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("squaring failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestWFp2MulByNonResidue(t *testing.T) {
|
|
f := newFp2()
|
|
a, b, c0, c1 := new(fe2), new(fe2), new(fe2), new(fe2)
|
|
w0, w1, w2, w3 := new(wfe2), new(wfe2), new(wfe2), new(wfe2)
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
r := new(fe2)
|
|
|
|
f.mul(r, a, b)
|
|
wfp2Mul(w0, a, b)
|
|
|
|
mulByNonResidue(c0, r)
|
|
wfp2MulByNonResidue(w1, w0)
|
|
w2.set(w0)
|
|
wfp2MulByNonResidueAssign(w2)
|
|
_wfp2MulByNonResidue(w3, w0)
|
|
if !w1.equal(w2) {
|
|
t.Fatal("mul by non residue failed")
|
|
}
|
|
if !w1.equal(w3) {
|
|
t.Fatal("mul by non residue failed")
|
|
}
|
|
c1.fromWide(w1)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("mul by non residue failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6Serialization(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
b, err := f.fromBytes(f.toBytes(a))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !a.equal(b) {
|
|
t.Fatal("serialization")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6AdditionProperties(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
zero := f.zero()
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
b, _ := new(fe6).rand(rand.Reader)
|
|
c1 := f.new()
|
|
c2 := f.new()
|
|
fp6Add(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
fp6Sub(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
fp6Double(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
fp6Neg(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("-0 == 0")
|
|
}
|
|
fp6Sub(c1, zero, a)
|
|
fp6Neg(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
fp6Double(c1, a)
|
|
fp6Add(c2, a, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
fp6Add(c1, a, b)
|
|
fp6Add(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
fp6Sub(c1, a, b)
|
|
fp6Sub(c2, b, a)
|
|
fp6Neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
cx, _ := new(fe6).rand(rand.Reader)
|
|
fp6Add(c1, a, b)
|
|
fp6Add(c1, c1, cx)
|
|
fp6Add(c2, a, cx)
|
|
fp6Add(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a + b) + c == (a + c ) + b")
|
|
}
|
|
fp6Sub(c1, a, b)
|
|
fp6Sub(c1, c1, cx)
|
|
fp6Sub(c2, a, cx)
|
|
fp6Sub(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a - b) - c == (a - c ) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6AdditionPropertiesAssigned(t *testing.T) {
|
|
for i := 0; i < fuz; i++ {
|
|
zero := new(fe6).zero()
|
|
a, b := new(fe6), new(fe6)
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
fp6AddAssign(a, zero)
|
|
if !a.equal(b) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
fp6SubAssign(a, zero)
|
|
if !a.equal(b) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
a.set(zero)
|
|
fp6DoubleAssign(a)
|
|
if !a.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
a.set(zero)
|
|
fp6SubAssign(a, b)
|
|
fp6Neg(b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b.set(a)
|
|
fp6DoubleAssign(a)
|
|
fp6AddAssign(b, b)
|
|
if !a.equal(b) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c1, c2 := new(fe6).set(a), new(fe6).set(b)
|
|
fp6AddAssign(c1, b)
|
|
fp6AddAssign(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c1.set(a)
|
|
c2.set(b)
|
|
fp6SubAssign(c1, b)
|
|
fp6SubAssign(c2, a)
|
|
fp6Neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
c, _ := new(fe6).rand(rand.Reader)
|
|
a0 := new(fe6).set(a)
|
|
fp6AddAssign(a, b)
|
|
fp6AddAssign(a, c)
|
|
fp6AddAssign(b, c)
|
|
fp6AddAssign(b, a0)
|
|
if !a.equal(b) {
|
|
t.Fatal("(a + b) + c == (b + c) + a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
_, _ = c.rand(rand.Reader)
|
|
a0.set(a)
|
|
fp6SubAssign(a, b)
|
|
fp6SubAssign(a, c)
|
|
fp6SubAssign(a0, c)
|
|
fp6SubAssign(a0, b)
|
|
if !a.equal(a0) {
|
|
t.Fatal("(a - b) - c == (a - c) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6LazyOperations(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
b, _ := new(fe6).rand(rand.Reader)
|
|
c, _ := new(fe6).rand(rand.Reader)
|
|
c0 := new(fe6)
|
|
c1 := new(fe6)
|
|
fp6Ladd(c0, a, b)
|
|
fp6Add(c1, a, b)
|
|
f.mulAssign(c0, c)
|
|
f.mulAssign(c1, c)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("(a + b) * c == (a l+ b) * c")
|
|
}
|
|
if !c0.equal(c1) {
|
|
t.Fatal("(a + b) * c == (a l+ b) * c")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6SparseMultiplication(t *testing.T) {
|
|
fp6 := newFp6(nil)
|
|
var a, b, u *fe6
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ = new(fe6).rand(rand.Reader)
|
|
b, _ = new(fe6).rand(rand.Reader)
|
|
u, _ = new(fe6).rand(rand.Reader)
|
|
b[2].zero()
|
|
fp6.mul(u, a, b)
|
|
fp6._mul01(a, a, &b[0], &b[1])
|
|
if !a.equal(u) {
|
|
t.Fatal("mul by 01")
|
|
}
|
|
}
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ = new(fe6).rand(rand.Reader)
|
|
b, _ = new(fe6).rand(rand.Reader)
|
|
u, _ = new(fe6).rand(rand.Reader)
|
|
b[2].zero()
|
|
b[0].zero()
|
|
fp6.mul(u, a, b)
|
|
fp6._mul1(a, a, &b[1])
|
|
if !a.equal(u) {
|
|
t.Fatal("mul by 1")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6MultiplicationProperties(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
b, _ := new(fe6).rand(rand.Reader)
|
|
zero := f.zero()
|
|
one := f.one()
|
|
c1, c2 := f.new(), f.new()
|
|
f.mul(c1, a, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
f.mul(c1, a, one)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
f.mul(c1, a, b)
|
|
f.mul(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
cx, _ := new(fe6).rand(rand.Reader)
|
|
f.mul(c1, a, b)
|
|
f.mul(c1, c1, cx)
|
|
f.mul(c2, cx, b)
|
|
f.mul(c2, c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
f.square(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("0^2 == 0")
|
|
}
|
|
f.square(a, one)
|
|
if !a.equal(one) {
|
|
t.Fatal("1^2 == 1")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
f.square(c1, a)
|
|
f.mul(c2, a, a)
|
|
if !c2.equal(c1) {
|
|
t.Fatal("a^2 == a*a")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6MultiplicationPropertiesAssigned(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
zero, one := new(fe6).zero(), new(fe6).one()
|
|
f.mulAssign(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
a0 := new(fe6).set(a)
|
|
f.mulAssign(a, one)
|
|
if !a.equal(a0) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b, _ := new(fe6).rand(rand.Reader)
|
|
a0.set(a)
|
|
f.mulAssign(a, b)
|
|
f.mulAssign(b, a0)
|
|
if !a.equal(b) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
c, _ := new(fe6).rand(rand.Reader)
|
|
a0.set(a)
|
|
f.mulAssign(a, b)
|
|
f.mulAssign(a, c)
|
|
f.mulAssign(a0, c)
|
|
f.mulAssign(a0, b)
|
|
if !a.equal(a0) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6Exponentiation(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
u := f.new()
|
|
f.exp(u, a, big.NewInt(0))
|
|
if !u.equal(f.one()) {
|
|
t.Fatal("a^0 == 1")
|
|
}
|
|
f.exp(u, a, big.NewInt(1))
|
|
if !u.equal(a) {
|
|
t.Fatal("a^1 == a")
|
|
}
|
|
v := f.new()
|
|
f.exp(v, a, big.NewInt(8))
|
|
f.square(u, a)
|
|
f.square(u, u)
|
|
f.square(u, u)
|
|
if !u.equal(v) {
|
|
t.Fatal("((a^2)^2)^2 == a^8", i)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6Inversion(t *testing.T) {
|
|
f := newFp6(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
u := f.new()
|
|
zero := f.zero()
|
|
one := f.one()
|
|
f.inverse(u, zero)
|
|
if !u.equal(zero) {
|
|
t.Fatal("(0^-1) == 0)")
|
|
}
|
|
f.inverse(u, one)
|
|
if !u.equal(one) {
|
|
t.Fatal("(1^-1) == 1)")
|
|
}
|
|
a, _ := new(fe6).rand(rand.Reader)
|
|
f.inverse(u, a)
|
|
f.mul(u, u, a)
|
|
if !u.equal(one) {
|
|
t.Fatal("(r*a) * r*(a^-1) == r)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6MultiplicationCross(t *testing.T) {
|
|
f := newFp6(nil)
|
|
a, b, c0, c1, c2, c3 := new(fe6), new(fe6), new(fe6), new(fe6), new(fe6), new(fe6)
|
|
w0 := new(wfe6)
|
|
for i := 0; i < fuz; i++ {
|
|
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
f.wmul(w0, a, b)
|
|
c0.fromWide(w0)
|
|
f.mul(c1, a, b)
|
|
f._mul(c2, a, b)
|
|
c3.set(a)
|
|
f.mulAssign(c3, b)
|
|
if !c0.equal(c1) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
if !c0.equal(c2) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
if !c0.equal(c3) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
func TestFp6SquareCross(t *testing.T) {
|
|
f := newFp6(nil)
|
|
a, c0, c1, c2 := new(fe6), new(fe6), new(fe6), new(fe6)
|
|
w0 := new(wfe6)
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a.rand(rand.Reader)
|
|
f.wsquare(w0, a)
|
|
c0.fromWide(w0)
|
|
f.square(c1, a)
|
|
f._square(c2, a)
|
|
|
|
if !c0.equal(c2) {
|
|
t.Fatal("squaring failed")
|
|
}
|
|
if !c0.equal(c1) {
|
|
t.Fatal("squaring failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp6SparseMultiplicationCross(t *testing.T) {
|
|
f := newFp6(nil)
|
|
a, c0, c1, c2 := new(fe6), new(fe6), new(fe6), new(fe6)
|
|
w0 := new(wfe6)
|
|
for i := 0; i < fuz; i++ {
|
|
// mul01
|
|
{
|
|
_, _ = a.rand(rand.Reader)
|
|
b0, _ := new(fe2).rand(rand.Reader)
|
|
b1, _ := new(fe2).rand(rand.Reader)
|
|
b := new(fe6)
|
|
b[0].set(b0)
|
|
b[1].set(b1)
|
|
|
|
f.wmul01(w0, a, b0, b1)
|
|
c0.fromWide(w0)
|
|
|
|
f._mul01(c1, a, b0, b1)
|
|
f._mul(c2, a, b)
|
|
|
|
if !c2.equal(c1) {
|
|
t.Fatal("sparse multiplication 01 failed")
|
|
}
|
|
|
|
if !c0.equal(c1) {
|
|
t.Fatal("sparse multiplication 01 failed")
|
|
}
|
|
|
|
}
|
|
// mul0
|
|
{
|
|
_, _ = a.rand(rand.Reader)
|
|
b1, _ := new(fe2).rand(rand.Reader)
|
|
b := new(fe6)
|
|
b[1].set(b1)
|
|
|
|
f.wmul1(w0, a, b1)
|
|
c0.fromWide(w0)
|
|
f._mul1(c1, a, b1)
|
|
f._mul(c2, a, b)
|
|
|
|
if !c2.equal(c0) {
|
|
t.Fatal("sparse multiplication 0 failed")
|
|
}
|
|
if !c2.equal(c1) {
|
|
t.Fatal("sparse multiplication 0 failed")
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12Serialization(t *testing.T) {
|
|
f := newFp12(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe12).rand(rand.Reader)
|
|
b, err := f.fromBytes(f.toBytes(a))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if !a.equal(b) {
|
|
t.Fatal("serialization")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12AdditionProperties(t *testing.T) {
|
|
f := newFp12(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
zero := f.zero()
|
|
a, _ := new(fe12).rand(rand.Reader)
|
|
b, _ := new(fe12).rand(rand.Reader)
|
|
c1 := f.new()
|
|
c2 := f.new()
|
|
fp12Add(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a + 0 == a")
|
|
}
|
|
fp12Sub(c1, a, zero)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a - 0 == a")
|
|
}
|
|
fp12Double(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("2 * 0 == 0")
|
|
}
|
|
fp12Neg(c1, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("-0 == 0")
|
|
}
|
|
fp12Sub(c1, zero, a)
|
|
fp12Neg(c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("0-a == -a")
|
|
}
|
|
fp12Double(c1, a)
|
|
fp12Add(c2, a, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("2 * a == a + a")
|
|
}
|
|
fp12Add(c1, a, b)
|
|
fp12Add(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a + b = b + a")
|
|
}
|
|
fp12Sub(c1, a, b)
|
|
fp12Sub(c2, b, a)
|
|
fp12Neg(c2, c2)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a - b = - ( b - a )")
|
|
}
|
|
cx, _ := new(fe12).rand(rand.Reader)
|
|
fp12Add(c1, a, b)
|
|
fp12Add(c1, c1, cx)
|
|
fp12Add(c2, a, cx)
|
|
fp12Add(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a + b) + c == (a + c ) + b")
|
|
}
|
|
fp12Sub(c1, a, b)
|
|
fp12Sub(c1, c1, cx)
|
|
fp12Sub(c2, a, cx)
|
|
fp12Sub(c2, c2, b)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a - b) - c == (a - c ) -b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12MultiplicationProperties(t *testing.T) {
|
|
f := newFp12(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe12).rand(rand.Reader)
|
|
b, _ := new(fe12).rand(rand.Reader)
|
|
zero := f.zero()
|
|
one := f.one()
|
|
c1, c2 := f.new(), f.new()
|
|
f.mul(c1, a, zero)
|
|
if !c1.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
f.mul(c1, a, one)
|
|
if !c1.equal(a) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
f.mul(c1, a, b)
|
|
f.mul(c2, b, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
cx, _ := new(fe12).rand(rand.Reader)
|
|
f.mul(c1, a, b)
|
|
f.mul(c1, c1, cx)
|
|
f.mul(c2, cx, b)
|
|
f.mul(c2, c2, a)
|
|
if !c1.equal(c2) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
f.square(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("0^2 == 0")
|
|
}
|
|
f.square(a, one)
|
|
if !a.equal(one) {
|
|
t.Fatal("1^2 == 1")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
f.square(c1, a)
|
|
f.mul(c2, a, a)
|
|
if !c2.equal(c1) {
|
|
t.Fatal("a^2 == a*a")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12MultiplicationPropertiesAssigned(t *testing.T) {
|
|
f := newFp12(nil)
|
|
zero, one := new(fe12).zero(), new(fe12).one()
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe12).rand(rand.Reader)
|
|
f.mulAssign(a, zero)
|
|
if !a.equal(zero) {
|
|
t.Fatal("a * 0 == 0")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
a0 := new(fe12).set(a)
|
|
f.mulAssign(a, one)
|
|
if !a.equal(a0) {
|
|
t.Fatal("a * 1 == a")
|
|
}
|
|
_, _ = a.rand(rand.Reader)
|
|
b, _ := new(fe12).rand(rand.Reader)
|
|
a0.set(a)
|
|
f.mulAssign(a, b)
|
|
f.mulAssign(b, a0)
|
|
if !a.equal(b) {
|
|
t.Fatal("a * b == b * a")
|
|
}
|
|
c, _ := new(fe12).rand(rand.Reader)
|
|
a0.set(a)
|
|
f.mul(a, a, b)
|
|
f.mul(a, a, c)
|
|
f.mul(a0, a0, c)
|
|
f.mul(a0, a0, b)
|
|
if !a.equal(a0) {
|
|
t.Fatal("(a * b) * c == (a * c) * b")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12SparseMultiplication(t *testing.T) {
|
|
fp12 := newFp12(nil)
|
|
var a, b, u *fe12
|
|
for j := 0; j < fuz; j++ {
|
|
a, _ = new(fe12).rand(rand.Reader)
|
|
b, _ = new(fe12).rand(rand.Reader)
|
|
u, _ = new(fe12).rand(rand.Reader)
|
|
b[0][2].zero()
|
|
b[1][0].zero()
|
|
b[1][2].zero()
|
|
fp12.mul(u, a, b)
|
|
fp12.mul014(a, &b[0][0], &b[0][1], &b[1][1])
|
|
if !a.equal(u) {
|
|
t.Fatal("mul by 01")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12Exponentiation(t *testing.T) {
|
|
f := newFp12(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
a, _ := new(fe12).rand(rand.Reader)
|
|
u := f.new()
|
|
f.exp(u, a, big.NewInt(0))
|
|
if !u.equal(f.one()) {
|
|
t.Fatal("a^0 == 1")
|
|
}
|
|
f.exp(u, a, big.NewInt(1))
|
|
if !u.equal(a) {
|
|
t.Fatal("a^1 == a")
|
|
}
|
|
v := f.new()
|
|
f.mul(u, a, a)
|
|
f.mul(u, u, u)
|
|
f.mul(u, u, u)
|
|
f.exp(v, a, big.NewInt(8))
|
|
if !u.equal(v) {
|
|
t.Fatal("((a^2)^2)^2 == a^8")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12Inversion(t *testing.T) {
|
|
f := newFp12(nil)
|
|
for i := 0; i < fuz; i++ {
|
|
u := f.new()
|
|
zero := f.zero()
|
|
one := f.one()
|
|
f.inverse(u, zero)
|
|
if !u.equal(zero) {
|
|
t.Fatal("(0^-1) == 0)")
|
|
}
|
|
f.inverse(u, one)
|
|
if !u.equal(one) {
|
|
t.Fatal("(1^-1) == 1)")
|
|
}
|
|
a, _ := new(fe12).rand(rand.Reader)
|
|
f.inverse(u, a)
|
|
f.mul(u, u, a)
|
|
if !u.equal(one) {
|
|
t.Fatal("(r*a) * r*(a^-1) == r)")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFrobeniusMapping2(t *testing.T) {
|
|
f := newFp2()
|
|
a, _ := new(fe2).rand(rand.Reader)
|
|
b0, b1, b2, b3 := new(fe2), new(fe2), new(fe2), new(fe2)
|
|
f.exp(b0, a, modulus.big())
|
|
fp2Conjugate(b1, a)
|
|
b2.set(a)
|
|
f.frobeniusMap1(b2)
|
|
b3.set(a)
|
|
f.frobeniusMap(b3, 1)
|
|
if !b0.equal(b3) {
|
|
t.Fatal("frobenius map failed")
|
|
}
|
|
if !b1.equal(b3) {
|
|
t.Fatal("frobenius map failed")
|
|
}
|
|
if !b2.equal(b3) {
|
|
t.Fatal("frobenius map failed")
|
|
}
|
|
}
|
|
|
|
func TestFrobeniusMapping6(t *testing.T) {
|
|
{
|
|
f := newFp2()
|
|
z := nonResidue2
|
|
for i := 0; i < 6; i++ {
|
|
p, r, e := modulus.big(), new(fe2), big.NewInt(0)
|
|
// p ^ i
|
|
p.Exp(p, big.NewInt(int64(i)), nil)
|
|
// (p ^ i - 1) / 3
|
|
e.Sub(p, big.NewInt(1)).Div(e, big.NewInt(3))
|
|
// r = z ^ (p ^ i - 1) / 3
|
|
f.exp(r, z, e)
|
|
if !r.equal(&frobeniusCoeffs61[i]) {
|
|
t.Fatalf("bad frobenius fp6 1q coefficient")
|
|
}
|
|
}
|
|
for i := 0; i < 6; i++ {
|
|
p, r, e := modulus.big(), new(fe2), big.NewInt(0)
|
|
// p ^ i
|
|
p.Exp(p, big.NewInt(int64(i)), nil).Mul(p, big.NewInt(2))
|
|
// (2 * p ^ i - 2) / 3
|
|
e.Sub(p, big.NewInt(2)).Div(e, big.NewInt(3))
|
|
// r = z ^ (2 * p ^ i - 2) / 3
|
|
f.exp(r, z, e)
|
|
if !r.equal(&frobeniusCoeffs62[i]) {
|
|
t.Fatalf("bad frobenius fp6 2q coefficient")
|
|
}
|
|
}
|
|
}
|
|
f := newFp6(nil)
|
|
r0, r1 := f.new(), f.new()
|
|
e, _ := new(fe6).rand(rand.Reader)
|
|
r0.set(e)
|
|
r1.set(e)
|
|
f.frobeniusMap(r1, 1)
|
|
f.frobeniusMap1(r0)
|
|
if !r0.equal(r1) {
|
|
t.Fatalf("frobenius mapping by 1 failed")
|
|
}
|
|
r0.set(e)
|
|
r1.set(e)
|
|
f.frobeniusMap(r1, 2)
|
|
f.frobeniusMap2(r0)
|
|
if !r0.equal(r1) {
|
|
t.Fatalf("frobenius mapping by 2 failed")
|
|
}
|
|
r0.set(e)
|
|
r1.set(e)
|
|
f.frobeniusMap(r1, 3)
|
|
f.frobeniusMap3(r0)
|
|
if !r0.equal(r1) {
|
|
t.Fatalf("frobenius mapping by 3 failed")
|
|
}
|
|
}
|
|
|
|
func TestFrobeniusMapping12(t *testing.T) {
|
|
{
|
|
f := newFp2()
|
|
z := nonResidue2
|
|
for i := 0; i < 12; i++ {
|
|
p, r, e := modulus.big(), new(fe2), big.NewInt(0)
|
|
// p ^ i
|
|
p.Exp(p, big.NewInt(int64(i)), nil)
|
|
// (p ^ i - 1) / 6
|
|
e.Sub(p, big.NewInt(1)).Div(e, big.NewInt(6))
|
|
// r = z ^ (p ^ i - 1) / 6
|
|
f.exp(r, z, e)
|
|
if !r.equal(&frobeniusCoeffs12[i]) {
|
|
t.Fatalf("bad frobenius fp12 coefficient")
|
|
}
|
|
}
|
|
}
|
|
f := newFp12(nil)
|
|
r0, r1 := f.new(), f.new()
|
|
e, _ := new(fe12).rand(rand.Reader)
|
|
p := modulus.big()
|
|
f.exp(r0, e, p)
|
|
r1.set(e)
|
|
f.frobeniusMap1(r1)
|
|
if !r0.equal(r1) {
|
|
t.Fatalf("frobenius mapping by 1 failed")
|
|
}
|
|
p.Mul(p, modulus.big())
|
|
f.exp(r0, e, p)
|
|
r1.set(e)
|
|
f.frobeniusMap2(r1)
|
|
if !r0.equal(r1) {
|
|
t.Fatalf("frobenius mapping by 2 failed")
|
|
}
|
|
p.Mul(p, modulus.big())
|
|
f.exp(r0, e, p)
|
|
r1.set(e)
|
|
f.frobeniusMap3(r1)
|
|
if !r0.equal(r1) {
|
|
t.Fatalf("frobenius mapping by 2 failed")
|
|
}
|
|
}
|
|
|
|
func TestFp12MultiplicationCross(t *testing.T) {
|
|
f := newFp12(nil)
|
|
a, b, c0, c1, c2 := new(fe12), new(fe12), new(fe12), new(fe12), new(fe12)
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a.rand(rand.Reader)
|
|
_, _ = b.rand(rand.Reader)
|
|
f.mul(c0, a, b)
|
|
c1.set(a)
|
|
f.mulAssign(c1, b)
|
|
f._mul(c2, a, b)
|
|
|
|
if !c0.equal(c1) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
if !c0.equal(c2) {
|
|
t.Fatal("multiplication failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp12SparseMultiplicationCross(t *testing.T) {
|
|
f := newFp12(nil)
|
|
a, c0, c1 := new(fe12), new(fe12), new(fe12)
|
|
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a.rand(rand.Reader)
|
|
b0, _ := new(fe2).rand(rand.Reader)
|
|
b1, _ := new(fe2).rand(rand.Reader)
|
|
b4, _ := new(fe2).rand(rand.Reader)
|
|
b := new(fe12)
|
|
b[0][0].set(b0)
|
|
b[0][1].set(b1)
|
|
b[1][1].set(b4)
|
|
|
|
c0.set(a)
|
|
f.mul014(c0, b0, b1, b4)
|
|
f._mul(c1, a, b)
|
|
|
|
if !c0.equal(c1) {
|
|
t.Fatal("sparse multiplication 014 failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestFp4MultiplicationCross(t *testing.T) {
|
|
f := newFp12(nil)
|
|
a0, a1, b0, b1 := new(fe2), new(fe2), new(fe2), new(fe2)
|
|
c0, c1 := new(fe2), new(fe2)
|
|
|
|
for i := 0; i < fuz; i++ {
|
|
_, _ = a0.rand(rand.Reader)
|
|
_, _ = a1.rand(rand.Reader)
|
|
_, _ = b0.rand(rand.Reader)
|
|
_, _ = b1.rand(rand.Reader)
|
|
c0.set(a0)
|
|
c1.set(a1)
|
|
|
|
f._fp4Square(a0, a1, b0, b1)
|
|
f.fp4Square(c0, c1, b0, b1)
|
|
|
|
if !a0.equal(c0) {
|
|
t.Fatal("fp4 multiplication failed")
|
|
}
|
|
if !a1.equal(c1) {
|
|
t.Fatal("fp4 multiplication failed")
|
|
}
|
|
}
|
|
}
|
|
|
|
func BenchmarkFpMul(t *testing.B) {
|
|
a, _ := new(fe).rand(rand.Reader)
|
|
b, _ := new(fe).rand(rand.Reader)
|
|
c := new(fe)
|
|
t.ResetTimer()
|
|
for i := 0; i < t.N; i++ {
|
|
mul(c, a, b)
|
|
}
|
|
}
|
|
|
|
func (fe *wfe) bytes() []byte {
|
|
out := make([]byte, fpByteSize*2)
|
|
var a int
|
|
for i := 0; i < 2*fpNumberOfLimbs; i++ {
|
|
a = fpByteSize*2 - i*8
|
|
out[a-1] = byte(fe[i])
|
|
out[a-2] = byte(fe[i] >> 8)
|
|
out[a-3] = byte(fe[i] >> 16)
|
|
out[a-4] = byte(fe[i] >> 24)
|
|
out[a-5] = byte(fe[i] >> 32)
|
|
out[a-6] = byte(fe[i] >> 40)
|
|
out[a-7] = byte(fe[i] >> 48)
|
|
out[a-8] = byte(fe[i] >> 56)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func (fe *wfe) equal(fe2 *wfe) bool {
|
|
return fe2[0] == fe[0] && fe2[1] == fe[1] && fe2[2] == fe[2] && fe2[3] == fe[3] && fe2[4] == fe[4] && fe2[5] == fe[5] && fe2[6] == fe[6] && fe2[7] == fe[7] && fe2[8] == fe[8] && fe2[9] == fe[9] && fe2[10] == fe[10] && fe2[11] == fe[11]
|
|
}
|
|
|
|
func (fe *wfe2) equal(fe2 *wfe2) bool {
|
|
return fe[0].equal(&fe2[0]) && fe[1].equal(&fe2[1])
|
|
}
|
|
|
|
func _fp2MulByNonResidue(c, a *fe2) {
|
|
t0 := &fe{}
|
|
add(t0, &a[0], &a[1])
|
|
sub(&c[0], &a[0], &a[1])
|
|
c[1].set(t0)
|
|
}
|
|
|
|
func _wfp2Add(c, a, b *wfe2) {
|
|
wadd(&c[0], &a[0], &b[0])
|
|
wadd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func _wfp2Ladd(c, a, b *wfe2) {
|
|
lwadd(&c[0], &a[0], &b[0])
|
|
lwadd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func _wfp2AddMixed(c, a, b *wfe2) {
|
|
wadd(&c[0], &a[0], &b[0])
|
|
lwadd(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func _wfp2Sub(c, a, b *wfe2) {
|
|
wsub(&c[0], &a[0], &b[0])
|
|
wsub(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func _wfp2SubMixed(c, a, b *wfe2) {
|
|
wsub(&c[0], &a[0], &b[0])
|
|
lwsub(&c[1], &a[1], &b[1])
|
|
}
|
|
|
|
func _wfp2Double(c, a *wfe2) {
|
|
wdouble(&c[0], &a[0])
|
|
wdouble(&c[1], &a[1])
|
|
}
|
|
|
|
func _wfp2MulByNonResidue(c, a *wfe2) {
|
|
wt0 := &wfe{}
|
|
wadd(wt0, &a[0], &a[1])
|
|
wsub(&c[0], &a[0], &a[1])
|
|
c[1].set(wt0)
|
|
}
|
|
|
|
func _wfp2Mul(c *wfe2, a, b *fe2) {
|
|
wt0, wt1 := new(wfe), new(wfe)
|
|
t0, t1 := new(fe), new(fe)
|
|
wmul(wt0, &a[0], &b[0]) // a0b0
|
|
wmul(wt1, &a[1], &b[1]) // a1b1
|
|
wsub(&c[0], wt0, wt1) // c0 = a0b0 - a1b1
|
|
lwaddAssign(wt0, wt1) // a0b0 + a1b1
|
|
ladd(t0, &a[0], &a[1]) // a0 + a1
|
|
ladd(t1, &b[0], &b[1]) // b0 + b1
|
|
wmul(wt1, t0, t1) // (a0 + a1)(b0 + b1)
|
|
lwsub(&c[1], wt1, wt0) // c1 = (a0 + a1)(b0 + b1) - (a0b0 + a1b1)
|
|
}
|
|
|
|
func _wfp2Square(c *wfe2, a *fe2) {
|
|
t0, t1, t2 := new(fe), new(fe), new(fe)
|
|
ladd(t0, &a[0], &a[1]) // (a0 + a1)
|
|
sub(t1, &a[0], &a[1]) // (a0 - a1)
|
|
ldouble(t2, &a[0]) // 2a0
|
|
wmul(&c[0], t1, t0) // c0 = (a0 + a1)(a0 - a1)
|
|
wmul(&c[1], t2, &a[1]) // c1 = 2a0a1
|
|
}
|
|
|
|
func (e *fp6) _mul(c, a, b *fe6) {
|
|
t0, t1, t2, t3, t4, t5 := new(fe2), new(fe2), new(fe2), new(fe2), new(fe2), new(fe2)
|
|
e.fp2.mul(t0, &a[0], &b[0]) // v0 = a0b0
|
|
e.fp2.mul(t1, &a[1], &b[1]) // v1 = a1b1
|
|
e.fp2.mul(t2, &a[2], &b[2]) // v2 = a2b2
|
|
fp2Add(t3, &a[1], &a[2]) // a1 + a2
|
|
fp2Add(t4, &b[1], &b[2]) // b1 + b2
|
|
e.fp2.mulAssign(t3, t4) // (a1 + a2)(b1 + b2)
|
|
fp2Add(t4, t1, t2) // v1 + v2
|
|
fp2SubAssign(t3, t4) // (a1 + a2)(b1 + b2) - v1 - v2
|
|
mulByNonResidueAssign(t3) // ((a1 + a2)(b1 + b2) - v1 - v2)β
|
|
fp2AddAssign(t3, t0) // c0 = ((a1 + a2)(b1 + b2) - v1 - v2)β + v0
|
|
fp2Add(t5, &a[0], &a[1]) // a0 + a1
|
|
fp2Add(t4, &b[0], &b[1]) // b0 + b1
|
|
e.fp2.mulAssign(t5, t4) // (a0 + a1)(b0 + b1)
|
|
fp2Add(t4, t0, t1) // v0 + v1
|
|
fp2SubAssign(t5, t4) // (a0 + a1)(b0 + b1) - v0 - v1
|
|
mulByNonResidue(t4, t2) // βv2
|
|
fp2Add(&c[1], t5, t4) // c1 = (a0 + a1)(b0 + b1) - v0 - v1 + βv2
|
|
fp2Add(t5, &a[0], &a[2]) // a0 + a2
|
|
fp2Add(t4, &b[0], &b[2]) // b0 + b2
|
|
e.fp2.mulAssign(t5, t4) // (a0 + a2)(b0 + b2)
|
|
fp2Add(t4, t0, t2) // v0 + v2
|
|
fp2SubAssign(t5, t4) // (a0 + a2)(b0 + b2) - v0 - v2
|
|
fp2Add(&c[2], t1, t5) // c2 = (a0 + a2)(b0 + b2) - v0 - v2 + v1
|
|
c[0].set(t3)
|
|
}
|
|
|
|
func (e *fp6) _mul01(c, a *fe6, b0, b1 *fe2) {
|
|
t0, t1, t2, t3, t4 := new(fe2), new(fe2), new(fe2), new(fe2), new(fe2)
|
|
e.fp2.mul(t0, &a[0], b0) // v0 = b0a0
|
|
e.fp2.mul(t1, &a[1], b1) // v1 = a1b1
|
|
fp2Add(t2, &a[1], &a[2]) // a1 + a2
|
|
e.fp2.mulAssign(t2, b1) // b1(a1 + a2)
|
|
fp2SubAssign(t2, t1) // b1(a1 + a2) - v1
|
|
mulByNonResidueAssign(t2) // (b1(a1 + a2) - v1)β
|
|
fp2Add(t3, &a[0], &a[2]) // a0 + a2
|
|
e.fp2.mulAssign(t3, b0) // b0(a0 + a2)
|
|
fp2SubAssign(t3, t0) // b0(a0 + a2) - v0
|
|
fp2Add(&c[2], t3, t1) // b0(a0 + a2) - v0 + v1
|
|
fp2Add(t4, b0, b1) // (b0 + b1)
|
|
fp2Add(t3, &a[0], &a[1]) // (a0 + a1)
|
|
e.fp2.mulAssign(t4, t3) // (a0 + a1)(b0 + b1)
|
|
fp2SubAssign(t4, t0) // (a0 + a1)(b0 + b1) - v0
|
|
fp2Sub(&c[1], t4, t1) // (a0 + a1)(b0 + b1) - v0 - v1
|
|
fp2Add(&c[0], t2, t0) // (b1(a1 + a2) - v1)β + v0
|
|
}
|
|
|
|
func (e *fp6) _mul1(c, a *fe6, b1 *fe2) {
|
|
t := new(fe2)
|
|
e.fp2.mul(t, &a[2], b1)
|
|
e.fp2.mul(&c[2], &a[1], b1)
|
|
e.fp2.mul(&c[1], &a[0], b1)
|
|
mulByNonResidue(&c[0], t)
|
|
}
|
|
|
|
func (e *fp6) _square(c, a *fe6) {
|
|
t0, t1, t2, t3, t4, t5 := new(fe2), new(fe2), new(fe2), new(fe2), new(fe2), new(fe2)
|
|
e.fp2.square(t0, &a[0])
|
|
e.fp2.mul(t1, &a[0], &a[1])
|
|
fp2DoubleAssign(t1)
|
|
fp2Sub(t2, &a[0], &a[1])
|
|
fp2AddAssign(t2, &a[2])
|
|
e.fp2.squareAssign(t2)
|
|
e.fp2.mul(t3, &a[1], &a[2])
|
|
fp2DoubleAssign(t3)
|
|
e.fp2.square(t4, &a[2])
|
|
mulByNonResidue(t5, t3)
|
|
fp2Add(&c[0], t0, t5)
|
|
mulByNonResidue(t5, t4)
|
|
fp2Add(&c[1], t1, t5)
|
|
fp2AddAssign(t1, t2)
|
|
fp2AddAssign(t1, t3)
|
|
fp2AddAssign(t0, t4)
|
|
fp2Sub(&c[2], t1, t0)
|
|
}
|
|
|
|
func (e *fp12) _mul(c, a, b *fe12) {
|
|
t0, t1, t2, t3 := new(fe6), new(fe6), new(fe6), new(fe6)
|
|
e.fp6.mul(t1, &a[0], &b[0]) // v0 = a0b0
|
|
e.fp6.mul(t2, &a[1], &b[1]) // v1 = a1b1
|
|
fp6Add(t0, &a[0], &a[1]) // a0 + a1
|
|
fp6Add(t3, &b[0], &b[1]) // b0 + b1
|
|
e.fp6.mulAssign(t0, t3) // (a0 + a1)(b0 + b1)
|
|
fp6SubAssign(t0, t1) // (a0 + a1)(b0 + b1) - v0
|
|
fp6Sub(&c[1], t0, t2) // c1 = (a0 + a1)(b0 + b1) - v0 - v1
|
|
e.fp6.mulByNonResidue(t2, t2) // βv1
|
|
fp6Add(&c[0], t1, t2) // c0 = v0 + βv1
|
|
}
|
|
|
|
func (e *fp12) _fp4Square(c0, c1, a0, a1 *fe2) {
|
|
t, fp2 := e.t2, e.fp2()
|
|
|
|
fp2.square(t[0], a0) // a0^2
|
|
fp2.square(t[1], a1) // a1^2
|
|
mulByNonResidue(t[2], t[1]) // βa1^2
|
|
fp2Add(c0, t[2], t[0]) // c0 = βa1^2 + a0^2
|
|
fp2Add(t[2], a0, a1) // a0 + a1
|
|
fp2.squareAssign(t[2]) // (a0 + a1)^2
|
|
fp2SubAssign(t[2], t[0]) // (a0 + a1)^2 - a0^2
|
|
fp2Sub(c1, t[2], t[1]) // (a0 + a1)^2 - a0^2 - a1^2
|
|
}
|