432 lines
11 KiB
Go
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)
|
|
}
|
|
}
|