Files
xgcl/sm/sm2/ec256/c256_generic_test.go
2026-05-27 23:03:00 +08:00

432 lines
11 KiB
Go

//go:build (!amd64 && !arm64) || generic32 || generic64
// +build !amd64,!arm64 generic32 generic64
// build when !amd64 AND !arm64 OR generic32 OR generic64
package ec256
import (
crand "crypto/rand"
"fmt"
"math/big"
"math/rand"
"testing"
"time"
)
func BenchmarkScalarMultc256(b *testing.B) {
b.ResetTimer()
// _, x, y, _ := elliptic.GenerateKey(c256, rand.Reader)
// priv, _, _, _ := elliptic.GenerateKey(c256, rand.Reader)
priv, _ := new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
bb := priv.Bytes()
b.ReportAllocs()
b.StartTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
// c256.ScalarMult(c256.Gx, c256.Gy, bb)
c256.ScalarBaseMult(bb)
}
})
}
func TestPointMul(t *testing.T) {
priv, _ := new(big.Int).SetString("115792089210356248762697446949407573529996955224135760342422259061068512044369", 10)
bb := priv.Bytes()
cnt := 5000
start := time.Now()
for i := 0; i < cnt; i++ {
// c256.ScalarMult(c256.Gx, c256.Gy, bb)
c256.ScalarBaseMult(bb)
}
end := time.Now()
elapsed := end.Sub(start)
fmt.Printf("SM2 Scalar Mul Point: %d PerSec\n", int(float64(cnt)/elapsed.Seconds()))
}
func TestReduceCarry(t *testing.T) {
// fmt.Printf("%08x\n", 1<<29-1-2<<21)
var inout [c256Limbs]uint32
var temp [c256Limbs]uint32
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < c256Limbs; i++ {
temp[i] = uint32(rnd.Int31()) & 0xFFFFFFF
inout[i] = temp[i]
}
var carry uint32 = 5
c256ReduceCarry(&inout, carry)
// for _, n := range inout {
// fmt.Printf("0x%08x, ", n)
// }
ret := c256ToBig(&inout)
fmt.Println(ret.Text(16))
s := c256ToBig(&temp)
r := big.NewInt(int64(carry))
r.Lsh(r, 257)
s.Add(s, r)
s.Mod(s, c256.P)
// c256FromBig(&inout, s)
fmt.Println(s.Text(16))
// c256FromBig(&inout, s)
// for _, n := range inout {
// fmt.Printf("0x%08x, ", n)
// }
ret.Sub(ret, s)
fmt.Println(ret)
}
func TestReduceDegree(t *testing.T) {
for j := uint64(0); j < 100000000; j++ {
if j%1000000 == 0 {
fmt.Println(j/10000, "万次pass")
}
var in [c256Limbs]uint32 //= [c256Limbs]uint32{0x1604a25, 0x6d1db34, 0x140458b9, 0xd3371b7, 0x79446ec, 0xd2bca28, 0xb98f19b, 0xc227f7c, 0xcaed5c}
var out [c256Limbs]uint32
var temp [c256Limbs]uint32 //= [c256Limbs]uint32{0xdb99003, 0x964a8c3, 0x1f7dc5a9, 0xc9db569, 0x1893e838, 0xeecb116, 0xca9ff4f, 0x68bd063, 0x11e538bf}
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < c256Limbs; i++ {
if i%2 == 0 {
temp[i] = uint32(rnd.Int()) & 0x1FFFFFFF
} else {
temp[i] = uint32(rnd.Int()) & 0xFFFFFFF
}
// fmt.Printf("0x%x,", temp[i])
}
for i := 0; i < c256Limbs; i++ {
if i%2 == 0 {
in[i] = uint32(rnd.Int31()) & 0x1FFFFFFF
} else {
in[i] = uint32(rnd.Int31()) & 0xFFFFFFF
}
// fmt.Printf("0x%x,", in[i])
}
ret := c256ToBig(&temp)
// fmt.Println("a:= ", ret.Text(16))
// ret = c256ToBig(&in)
// fmt.Println("b:= ", ret.Text(16))
c256Mul(&out, &in, &temp)
ret = c256ToBig(&out)
ret.Mod(ret, c256.P)
// fmt.Println("a*b=", ret.Text(16))
s := c256ToBig(&temp)
s.Mul(s, c256ToBig(&in))
s.Mul(s, c256RInverse)
s.Mod(s, c256.P)
// ret.Mod(ret, c256.P)
if ret.Cmp(s) != 0 {
fmt.Println("failed")
fmt.Println(ret.Text(16))
fmt.Println(s.Text(16))
fmt.Println("in:", in)
fmt.Println("temp:", temp)
fmt.Println("diff:", ret.Sub(ret, s).Text(16))
return
}
// ret.Sub(ret, s)
// fmt.Println("?0=", ret.Text(16))
}
fmt.Println("test over")
}
func TestInverse(t *testing.T) {
for i := 0; i < 100000; i++ {
if i%10000 == 0 {
fmt.Println(i, "pass")
}
var in [c256Limbs]uint32 //= [c256Limbs]uint32{0x1604a25, 0x6d1db34, 0x140458b9, 0xd3371b7, 0x79446ec, 0xd2bca28, 0xb98f19b, 0xc227f7c, 0xcaed5c}
var out [c256Limbs]uint32
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
for i := 0; i < c256Limbs; i++ {
if i%2 == 0 {
in[i] = uint32(rnd.Int()) & 0x1FFFFFFF
} else {
in[i] = uint32(rnd.Int()) & 0xFFFFFFF
}
// fmt.Printf("0x%x,", temp[i])
}
c256Invert(&out, &in) // in^(-1)*R
outInt := c256ToBig(&out)
outInt.Mod(outInt, c256.P)
// fmt.Println(outInt.Text(16))
inInt := c256ToBig(&in) // in * R
inInt.ModInverse(inInt, c256.P) // (in*R)^-1
inInt.Lsh(inInt, 257+257) // in^-1 * R
inInt.Mod(inInt, c256.P)
// fmt.Println(inInt.Text(16))
if inInt.Cmp(outInt) != 0 {
fmt.Println("Failed")
fmt.Println(in)
fmt.Println(new(big.Int).Sub(inInt, outInt).Text(16))
return
}
}
}
func TestGenTable32(t *testing.T) {
// Index | Index (binary) | Value
// 0 | 0000 | 0G (all zeros, omitted)
// 1 | 0001 | G
// 2 | 0010 | 2**64G
// 3 | 0011 | 2**64G + G
// 4 | 0100 | 2**128G
// 5 | 0101 | 2**128G + G
// 6 | 0110 | 2**128G + 2**64G
// 7 | 0111 | 2**128G + 2**64G + G
// 8 | 1000 | 2**192G
// 9 | 1001 | 2**192G + G
// 10 | 1010 | 2**192G + 2**64G
// 11 | 1011 | 2**192G + 2**64G + G
// 12 | 1100 | 2**192G + 2**128G
// 13 | 1101 | 2**192G + 2**128G + G
// 14 | 1110 | 2**192G + 2**128G + 2**64G
// 15 | 1111 | 2**192G + 2**128G + 2**64G + G
//
// The second table follows the same style, but the terms are 2**32G,
// 2**96G, 2**160G, 2**224G.
for i := 1; i < 16; i++ {
n := new(big.Int)
one := new(big.Int).SetInt64(1)
if i&0x08 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 192), n)
}
if i&0x04 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 128), n)
}
if i&0x02 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 64), n)
}
if i&0x01 > 0 {
n.Add(one, n)
}
// fmt.Println(n.Text(16))
x, y := c256.ScalarMult(c256.Gx, c256.Gy, n.Bytes())
var xOut, yOut [c256Limbs]uint32
c256FromBig(&xOut, x)
c256FromBig(&yOut, y)
for _, i := range xOut {
fmt.Printf("0x%x, ", i)
}
fmt.Println()
for _, i := range yOut {
fmt.Printf("0x%x, ", i)
}
fmt.Println()
}
for i := 1; i < 16; i++ {
n := new(big.Int)
one := new(big.Int).SetInt64(1)
if i&0x08 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 224), n)
}
if i&0x04 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 160), n)
}
if i&0x02 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 96), n)
}
if i&0x01 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 32), n)
}
// fmt.Println(n.Text(16))
x, y := c256.ScalarMult(c256.Gx, c256.Gy, n.Bytes())
var xOut, yOut [c256Limbs]uint32
c256FromBig(&xOut, x)
c256FromBig(&yOut, y)
for _, i := range xOut {
fmt.Printf("0x%x, ", i)
}
fmt.Println()
for _, i := range yOut {
fmt.Printf("0x%x, ", i)
}
fmt.Println()
}
}
// c256FromBig sets out = R*in.
func c256FromBig64(out *[5]uint64, in *big.Int) {
var bottom51Bits uint64 = 1<<51 - 1
var bottom52Bits uint64 = 1<<52 - 1
tmp := new(big.Int).Lsh(in, 257)
tmp.Mod(tmp, c256.P)
for i := 0; i < 5; i++ {
if bits := tmp.Bits(); len(bits) > 0 {
out[i] = uint64(bits[0]) & bottom51Bits
} else {
out[i] = 0
}
tmp.Rsh(tmp, 51)
i++
if i == 5 {
break
}
if bits := tmp.Bits(); len(bits) > 0 {
out[i] = uint64(bits[0]) & bottom52Bits
} else {
out[i] = 0
}
tmp.Rsh(tmp, 52)
}
}
func TestGenTable64(t *testing.T) {
// Index | Index (binary) | Value
// 0 | 0000 | 0G (all zeros, omitted)
// 1 | 0001 | G
// 2 | 0010 | 2**64G
// 3 | 0011 | 2**64G + G
// 4 | 0100 | 2**128G
// 5 | 0101 | 2**128G + G
// 6 | 0110 | 2**128G + 2**64G
// 7 | 0111 | 2**128G + 2**64G + G
// 8 | 1000 | 2**192G
// 9 | 1001 | 2**192G + G
// 10 | 1010 | 2**192G + 2**64G
// 11 | 1011 | 2**192G + 2**64G + G
// 12 | 1100 | 2**192G + 2**128G
// 13 | 1101 | 2**192G + 2**128G + G
// 14 | 1110 | 2**192G + 2**128G + 2**64G
// 15 | 1111 | 2**192G + 2**128G + 2**64G + G
//
// The second table follows the same style, but the terms are 2**32G,
// 2**96G, 2**160G, 2**224G.
for i := 1; i < 16; i++ {
n := new(big.Int)
one := new(big.Int).SetInt64(1)
if i&0x08 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 192), n)
}
if i&0x04 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 128), n)
}
if i&0x02 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 64), n)
}
if i&0x01 > 0 {
n.Add(one, n)
}
// fmt.Println(n.Text(16))
x, y := c256.ScalarMult(c256.Gx, c256.Gy, n.Bytes())
var xOut, yOut [5]uint64
c256FromBig64(&xOut, x)
c256FromBig64(&yOut, y)
for _, i := range xOut {
fmt.Printf("0x%xLLU, ", i)
}
fmt.Println()
for _, i := range yOut {
fmt.Printf("0x%xLLU, ", i)
}
fmt.Println()
}
for i := 1; i < 16; i++ {
n := new(big.Int)
one := new(big.Int).SetInt64(1)
if i&0x08 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 224), n)
}
if i&0x04 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 160), n)
}
if i&0x02 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 96), n)
}
if i&0x01 > 0 {
n.Add(new(big.Int).SetInt64(1).Lsh(one, 32), n)
}
// fmt.Println(n.Text(16))
x, y := c256.ScalarMult(c256.Gx, c256.Gy, n.Bytes())
var xOut, yOut [5]uint64
c256FromBig64(&xOut, x)
c256FromBig64(&yOut, y)
for _, i := range xOut {
fmt.Printf("0x%xLLU, ", i)
}
fmt.Println()
for _, i := range yOut {
fmt.Printf("0x%xLLU, ", i)
}
fmt.Println()
}
}
func TestPointMul2(t *testing.T) {
n, _ := crand.Int(crand.Reader, c256.N)
n.SetInt64(4)
//n.Set(c256.N)
//n.Sub(n, gmath.BigInt1)
//x, y := c256.ScalarBaseMult(n.Bytes())
//fmt.Println(x.Text(16), y.Text(16))
// n.Set(c256.N)
//xx, yy := c256.ScalarMult(c256.Gx, c256.Gy, n.Bytes())
xx, yy := c256.ScalarBaseMult(n.Bytes())
fmt.Println(xx.Text(16), yy.Text(16))
//fmt.Println(xx.Text(16), yy.Text(16))
// p := c256ToBig(&c256Zero31)
// fmt.Println(p.Text(16))
}
// FIXME c256ScalarBaseMult error when scalar = 0
func TestZeroScaleBaseMult(t *testing.T) {
n := new(big.Int)
var scalarReversed [32]byte
for i := 0; i < 32; i++ {
scalarReversed[i] = 0xcc
}
c256GetScalar(&scalarReversed, n.Bytes())
var x1, y1, z1 [c256Limbs]uint32
var tmp [17]uint64
c256PointDouble(&x1, &y1, &z1, &x1, &y1, &z1)
c256ReduceDegree(&z1, tmp)
c256ScalarBaseMult(&x1, &y1, &z1, &scalarReversed)
for _, z := range z1 {
if z != 0 {
t.Fail()
}
}
}
func TestReduce(t *testing.T) {
var tmp = [17]uint64{1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1}
var out [9]uint32
c256ReduceDegree(&out, tmp)
for i := 0; i < 9; i++ {
fmt.Println(out[i])
}
}
func TestIssue52075(t *testing.T) {
Gx, Gy := c256.Params().Gx, c256.Params().Gy
scalar := make([]byte, 33)
scalar[32] = 1
x, y := c256.ScalarBaseMult(scalar)
if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 {
t.Errorf("unexpected output (%v,%v)", x, y)
}
x, y = c256.ScalarMult(Gx, Gy, scalar)
if x.Cmp(Gx) != 0 || y.Cmp(Gy) != 0 {
t.Errorf("unexpected output (%v,%v)", x, y)
}
}