Files
xgcl/sm/sm9/internal/bn256/gfp_test.go
T
2026-05-27 23:03:00 +08:00

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))
}