619 lines
10 KiB
Go
619 lines
10 KiB
Go
package bn256
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"io"
|
|
"math/big"
|
|
"testing"
|
|
"time"
|
|
|
|
"xdx.jelly/xgcl/gmath"
|
|
)
|
|
|
|
var twoTo256 = new(big.Int).Lsh(big.NewInt(1), 256)
|
|
|
|
func gfPFromBigInt(A *big.Int) *gfP {
|
|
a := &gfP{}
|
|
buf := make([]byte, 32)
|
|
A.FillBytes(buf)
|
|
a.Unmarshal(buf)
|
|
montEncode(a, a)
|
|
return a
|
|
}
|
|
|
|
func randomInt(r io.Reader, max *big.Int) *big.Int {
|
|
a, _ := rand.Int(r, max)
|
|
return a
|
|
}
|
|
|
|
func (e *gfP) random(r io.Reader) *gfP {
|
|
e.Set(gfPFromBigInt(randomInt(r, P)))
|
|
return e
|
|
}
|
|
|
|
func (e *gfP2) random(r io.Reader) *gfP2 {
|
|
e.x.random(r)
|
|
e.y.random(r)
|
|
return e
|
|
}
|
|
|
|
func (f *gfP6) random(r io.Reader) *gfP6 {
|
|
f.x.random(r)
|
|
f.z.random(r)
|
|
f.y.random(r)
|
|
return f
|
|
}
|
|
|
|
func (f *gfP12) random(r io.Reader) *gfP12 {
|
|
f.x.random(r)
|
|
f.y.random(r)
|
|
return f
|
|
}
|
|
|
|
func testOp(t *testing.T, arg1, arg2 *big.Int, op1 func(*big.Int, *big.Int, *big.Int), op2 func(*gfP, *gfP, *gfP), equal func(*gfP, *gfP) bool) {
|
|
var a, b *gfP
|
|
|
|
a = gfPFromBigInt(arg1)
|
|
if arg2 != nil {
|
|
b = gfPFromBigInt(arg2)
|
|
}
|
|
|
|
C := new(big.Int)
|
|
op1(C, arg1, arg2)
|
|
c1 := gfPFromBigInt(C)
|
|
|
|
c2 := &gfP{}
|
|
op2(c2, a, b)
|
|
if !equal(c1, c2) {
|
|
fmt.Println("failed:")
|
|
fmt.Println("\ta =", a)
|
|
fmt.Println("\tb =", b)
|
|
fmt.Println("\tc1 =", c1)
|
|
fmt.Println("\tc2 =", c2)
|
|
t.Fatal()
|
|
}
|
|
}
|
|
|
|
func TestGFpSqrt(t *testing.T) {
|
|
for i := 0; i < 100000; i++ {
|
|
a := randomInt(rand.Reader, twoTo256)
|
|
a.Mul(a, a).Mod(a, N)
|
|
testOp(t,
|
|
big.NewInt(1),
|
|
nil,
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.ModSqrt(a, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
c.Sqrt(a)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
c := &gfP{}
|
|
gfpAdd(c, a, b)
|
|
return *a == *b || *c == gfP{}
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestGFpNeg(t *testing.T) {
|
|
a := &gfP{0xe56f9b27e351457c, 0x21f2934b1a7aeedb, 0xd603ab4ff58ec745, 0xb640000002a3a6f1}
|
|
gfpNeg(a, a)
|
|
if *a != (gfP{1, 0, 0, 0}) {
|
|
t.Fatal()
|
|
}
|
|
|
|
for i := 0; i < 1000000; i++ {
|
|
a := randomInt(rand.Reader, P)
|
|
a.Mul(a, a).Mod(a, N)
|
|
testOp(t,
|
|
randomInt(rand.Reader, P),
|
|
nil,
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Neg(a).Mod(c, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
gfpNeg(c, a)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
func TestGFpAdd(t *testing.T) {
|
|
for i := 0; i < 1000000; i++ {
|
|
testOp(t,
|
|
randomInt(rand.Reader, twoTo256),
|
|
randomInt(rand.Reader, twoTo256),
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Add(a, b).Mod(c, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
gfpAdd(c, a, b)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestGFpSub(t *testing.T) {
|
|
for i := 0; i < 1000000; i++ {
|
|
a := randomInt(rand.Reader, twoTo256)
|
|
b := randomInt(rand.Reader, twoTo256)
|
|
testOp(t,
|
|
a,
|
|
b.Sub(a, big.NewInt(1)),
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Sub(a, b).Mod(c, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
gfpSub(c, a, b)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestGFpHalf(t *testing.T) {
|
|
for i := 0; i < 100000; i++ {
|
|
testOp(t,
|
|
randomInt(rand.Reader, P),
|
|
nil,
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Set(a)
|
|
if c.Bit(0) == 1 {
|
|
c.Add(a, P)
|
|
}
|
|
c.Rsh(c, 1)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
c.half(a)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME: amd64平台不支持 a and b > p
|
|
func TestGFpMul(t *testing.T) {
|
|
for i := 0; i < 100000; i++ {
|
|
testOp(t,
|
|
randomInt(rand.Reader, P),
|
|
randomInt(rand.Reader, P),
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Mul(a, b).Mod(c, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
gfpMul(c, a, b)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
|
|
testOp(t,
|
|
randomInt(rand.Reader, twoTo256),
|
|
randomInt(rand.Reader, twoTo256),
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Mul(a, b).Mod(c, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
gfpMul(c, a, b)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
|
|
testOp(t,
|
|
new(big.Int).Sub(twoTo256, big.NewInt(int64(i+1))),
|
|
new(big.Int).Sub(twoTo256, big.NewInt(int64(i+2))),
|
|
func(c *big.Int, a *big.Int, b *big.Int) {
|
|
c.Mul(a, b).Mod(c, P)
|
|
},
|
|
func(c *gfP, a *gfP, b *gfP) {
|
|
gfpMul(c, a, b)
|
|
},
|
|
func(a *gfP, b *gfP) bool {
|
|
return *a == *b
|
|
},
|
|
)
|
|
}
|
|
}
|
|
|
|
func TestSpeedGFp(t *testing.T) {
|
|
a := newGFp(123)
|
|
b := newGFp(123)
|
|
c := newGFp(1)
|
|
|
|
buf := make([]byte, 32)
|
|
|
|
a.Marshal(buf)
|
|
A := new(big.Int).SetBytes(buf)
|
|
b.Marshal(buf)
|
|
B := new(big.Int).SetBytes(buf)
|
|
c.Marshal(buf)
|
|
C := new(big.Int).SetBytes(buf)
|
|
|
|
// fmt.Println(a, b, c)
|
|
begin := time.Now()
|
|
total := 10000000
|
|
for i := 0; i < total; i++ {
|
|
gfpMul(c, a, b)
|
|
}
|
|
elaspe := time.Since(begin)
|
|
fmt.Println("time: ", elaspe.Milliseconds(), "ms")
|
|
fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
|
|
|
|
begin = time.Now()
|
|
for i := 0; i < total; i++ {
|
|
C.Mul(A, B)
|
|
}
|
|
elaspe = time.Since(begin)
|
|
fmt.Println("time: ", elaspe.Milliseconds(), "ms")
|
|
fmt.Println(int(float64(total) / float64(elaspe.Milliseconds()) * 1000))
|
|
|
|
}
|
|
|
|
func (e *gfP2) Exp(a *gfP2, power *big.Int) *gfP2 {
|
|
sum := (&gfP2{}).SetOne()
|
|
t := &gfP2{}
|
|
|
|
for i := power.BitLen() - 1; i >= 0; i-- {
|
|
t.Square(sum)
|
|
if power.Bit(i) != 0 {
|
|
sum.Mul(t, a)
|
|
} else {
|
|
sum.Set(t)
|
|
}
|
|
}
|
|
|
|
e.Set(sum)
|
|
return e
|
|
}
|
|
|
|
// Exp set c = a^power and return c
|
|
func (f *gfP6) Exp(a *gfP6, power *big.Int) *gfP6 {
|
|
sum := (&gfP6{}).SetOne()
|
|
t := &gfP6{}
|
|
|
|
for i := power.BitLen() - 1; i >= 0; i-- {
|
|
t.Square(sum)
|
|
if power.Bit(i) != 0 {
|
|
sum.Mul(t, a)
|
|
} else {
|
|
sum.Set(t)
|
|
}
|
|
}
|
|
|
|
f.Set(sum)
|
|
return f
|
|
}
|
|
func TestGFp(t *testing.T) {
|
|
one := newGFp(1)
|
|
//one := &gfP{1}
|
|
//two := &gfP{2}
|
|
gfpMul(one, r2, one)
|
|
gfpMul(one, &gfP{1}, one)
|
|
montDecode(one, one)
|
|
if *one != (gfP{1}) {
|
|
t.Fail()
|
|
fmt.Println(one)
|
|
return
|
|
}
|
|
|
|
// a := (&gfP{}).random(rand.Reader)
|
|
a := &gfP{0x0a1c7970e5df544d, 0xe74504e9a96b56cc, 0xcda02d92d4d62924, 0x7d2bc576fdf597d1}
|
|
b := &gfP{}
|
|
c := &gfP{}
|
|
fmt.Println("Test Exponent")
|
|
b.exp(a, pMinus1)
|
|
//b.exp(a,[4]uint64{2,0,0,0})
|
|
//fmt.Println("a:", b)
|
|
//gfpMul(c,a,a)
|
|
//fmt.Println("c:",c)
|
|
//gfpSub(b,c,b)
|
|
// montDecode(b, b)
|
|
if *b != *newGFp(1) {
|
|
t.Fail()
|
|
fmt.Println(b)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
var rN1 = &gfP{0x0a1c7970e5df544d, 0xe74504e9a96b56cc, 0xcda02d92d4d62924, 0x7d2bc576fdf597d1}
|
|
fmt.Println("Test Rn")
|
|
gfpMul(b, rN1, r3)
|
|
montDecode(b, b)
|
|
if *b != (gfP{1}) {
|
|
t.Fail()
|
|
fmt.Println(b)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
fmt.Println("Test Invert")
|
|
a = newGFp(1)
|
|
c.Invert(a)
|
|
fmt.Println(a, c)
|
|
gfpMul(c, c, a)
|
|
montDecode(c, c)
|
|
if *c != (gfP{1}) {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
}
|
|
|
|
func TestGfP2(t *testing.T) {
|
|
|
|
p2Minus1 := new(big.Int)
|
|
p2Minus1.Mul(P, P)
|
|
p2Minus1.Sub(p2Minus1, gmath.BigInt1)
|
|
|
|
a := (&gfP2{}).random(rand.Reader)
|
|
b := &gfP2{}
|
|
c := &gfP2{}
|
|
|
|
fmt.Println("Test gfP2 mul and square")
|
|
fmt.Println("a: ", a)
|
|
b.Mul(a, a)
|
|
fmt.Println("a^2:", b)
|
|
|
|
c.Square(a)
|
|
fmt.Println("a*a:", c)
|
|
if !c.Sub(c, b).IsZero() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
fmt.Println("Test exponential")
|
|
c.Exp(a, p2Minus1)
|
|
if !c.IsOne() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
fmt.Println("Test Invert")
|
|
c.Invert(a)
|
|
c.Mul(c, a)
|
|
if !c.IsOne() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
}
|
|
|
|
func TestGFp2Sqrt(t *testing.T) {
|
|
for i := 0; i < 100000; i++ {
|
|
a := (&gfP2{}).random(rand.Reader)
|
|
a.Mul(a, a)
|
|
b := *a
|
|
if !a.Sqrt(a) {
|
|
t.Fatal()
|
|
}
|
|
a.Square(a)
|
|
if *a != b {
|
|
t.Fatal()
|
|
}
|
|
c := &gfP2{}
|
|
if !c.Sqrt(a) {
|
|
t.Fatal()
|
|
}
|
|
a.Square(c)
|
|
if *a != b {
|
|
t.Fatal()
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestGfP6(t *testing.T) {
|
|
p6Minus1 := new(big.Int)
|
|
p6Minus1.Exp(P, gmath.BigInt6, nil)
|
|
p6Minus1.Sub(p6Minus1, gmath.BigInt1)
|
|
|
|
a := (&gfP6{}).random(rand.Reader)
|
|
b := &gfP6{}
|
|
c := &gfP6{}
|
|
fmt.Println(a)
|
|
|
|
fmt.Println("Test gfP6 mul and square")
|
|
fmt.Println("a: ", a)
|
|
b.Mul(a, a)
|
|
fmt.Println("a^2:", b)
|
|
|
|
c.Square(a)
|
|
fmt.Println("a*a:", c)
|
|
if !c.Sub(c, b).IsZero() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
|
|
fmt.Println("Test exponential")
|
|
|
|
c.Exp(a, p6Minus1)
|
|
//c.Exp(a,gmath.BigInt1)
|
|
if !c.IsOne() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
fmt.Println("Test Invert")
|
|
c.Invert(a)
|
|
c.Mul(c, a)
|
|
if !c.IsOne() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
}
|
|
|
|
func TestGfP12(t *testing.T) {
|
|
p12Minus1 := new(big.Int)
|
|
p12Minus1.Exp(P, gmath.BigInt12, nil)
|
|
p12Minus1.Sub(p12Minus1, gmath.BigInt1)
|
|
|
|
a := (&gfP12{}).random(rand.Reader)
|
|
b := &gfP12{}
|
|
c := &gfP12{}
|
|
fmt.Println(a)
|
|
|
|
fmt.Println("Test gfP12 mul and square")
|
|
fmt.Println("a: ", a)
|
|
b.Mul(a, a)
|
|
fmt.Println("a^2:", b)
|
|
|
|
c.Square(a)
|
|
fmt.Println("a*a:", c)
|
|
if !c.Sub(c, b).IsZero() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
|
|
fmt.Println("Test exponential")
|
|
|
|
c.Exp(a, p12Minus1)
|
|
//c.Exp(a,gmath.BigInt1)
|
|
if !c.IsOne() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
fmt.Println("Test Invert")
|
|
c.Invert(a)
|
|
c.Mul(c, a)
|
|
if !c.IsOne() {
|
|
t.Fail()
|
|
fmt.Println(c)
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
}
|
|
|
|
func TestFrobenius6(t *testing.T) {
|
|
p2 := new(big.Int).Mul(P, P)
|
|
a := (&gfP6{}).random(rand.Reader)
|
|
b := &gfP6{}
|
|
c := &gfP6{}
|
|
b.Frobenius(a)
|
|
c.Exp(a, P)
|
|
if *b != *c {
|
|
fmt.Println("a:", a)
|
|
fmt.Println("b:", b)
|
|
fmt.Println("c:", c)
|
|
t.Fatal()
|
|
}
|
|
|
|
b.FrobeniusP2(a)
|
|
c.Exp(a, p2)
|
|
if *b != *c {
|
|
t.Fatal()
|
|
}
|
|
|
|
}
|
|
|
|
func TestFrobenius12(t *testing.T) {
|
|
p2 := new(big.Int).Mul(P, P)
|
|
a := (&gfP12{}).random(rand.Reader)
|
|
b := &gfP12{}
|
|
c := &gfP12{}
|
|
|
|
fmt.Println("Test Frobenius on GFP12")
|
|
b.Frobenius(a)
|
|
c.Exp(a, P)
|
|
if *b != *c {
|
|
fmt.Println("a:", a)
|
|
fmt.Println("b:", b)
|
|
fmt.Println("c:", c)
|
|
t.Fail()
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
|
|
fmt.Println("Test Frobenius2 on GFP12")
|
|
b.FrobeniusP2(a)
|
|
c.Exp(a, p2)
|
|
if *b != *c {
|
|
t.Fail()
|
|
return
|
|
}
|
|
fmt.Println("pass")
|
|
}
|
|
|
|
func present(p *gfP) string {
|
|
|
|
return fmt.Sprintf("gfP{0x%x,0x%x,0x%x,0x%x}", p[0], p[1], p[2], p[3])
|
|
}
|
|
|
|
// ExampleGFP12Gen generate gfP12Gen
|
|
func TestGFP12Gen(t *testing.T) {
|
|
e := Pair(&G1{*curveGen}, &G2{*twistGen}).p
|
|
fmt.Printf(`
|
|
var gfP12Gen *gfP12 = &gfP12{
|
|
x: gfP6{
|
|
x: gfP2{
|
|
x: %s,
|
|
y: %s,
|
|
},
|
|
y: gfP2{
|
|
x: %s,
|
|
y: %s,
|
|
},
|
|
z: gfP2{
|
|
x: %s,
|
|
y: %s,
|
|
},
|
|
},
|
|
y: gfP6{
|
|
x: gfP2{
|
|
x: %s,
|
|
y: %s,
|
|
},
|
|
y: gfP2{
|
|
x: %s,
|
|
y: %s,
|
|
},
|
|
z: gfP2{
|
|
x: %s,
|
|
y: %s,
|
|
},
|
|
},
|
|
}
|
|
`, present(&e.x.x.x),
|
|
present(&e.x.x.y),
|
|
present(&e.x.y.x),
|
|
present(&e.x.y.y),
|
|
present(&e.x.z.x),
|
|
present(&e.x.z.y),
|
|
present(&e.y.x.x),
|
|
present(&e.y.x.y),
|
|
present(&e.y.y.x),
|
|
present(&e.y.y.y),
|
|
present(&e.y.z.x),
|
|
present(&e.y.z.y))
|
|
}
|