init: v1.0.0
This commit is contained in:
@@ -0,0 +1,941 @@
|
||||
//go:build (amd64 || arm64) && !generic && !generic32 && !generic64
|
||||
// +build amd64 arm64
|
||||
// +build !generic
|
||||
// +build !generic32
|
||||
// +build !generic64
|
||||
|
||||
package ec256
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
// r^{-1} mod p
|
||||
var rModInverseP *big.Int
|
||||
var rModInverseN *big.Int
|
||||
var p *big.Int
|
||||
var n *big.Int
|
||||
|
||||
func init() {
|
||||
rModInverseP = new(big.Int)
|
||||
rModInverseP.SetInt64(1)
|
||||
rModInverseP.Lsh(rModInverseP, 256)
|
||||
rModInverseP.ModInverse(rModInverseP, c256.P)
|
||||
|
||||
rModInverseN = new(big.Int)
|
||||
rModInverseN.SetInt64(1)
|
||||
rModInverseN.Lsh(rModInverseN, 256)
|
||||
rModInverseN.ModInverse(rModInverseN, c256.N)
|
||||
|
||||
p = new(big.Int)
|
||||
p.Set(c256.P)
|
||||
n = new(big.Int)
|
||||
n.Set(c256.N)
|
||||
}
|
||||
|
||||
func randUint64(a []uint64) {
|
||||
buf := make([]byte, 8)
|
||||
for i := range a {
|
||||
rand.Read(buf)
|
||||
a[i] = binary.LittleEndian.Uint64(buf)
|
||||
}
|
||||
}
|
||||
|
||||
func assertEqual(a, b interface{}) {
|
||||
switch a.(type) {
|
||||
case *big.Int:
|
||||
if a.(*big.Int).Cmp(b.(*big.Int)) != 0 {
|
||||
panic("assert equal failed")
|
||||
}
|
||||
case []uint64:
|
||||
aa := a.([]uint64)
|
||||
bb := b.([]uint64)
|
||||
for i := 0; i < len(aa); i++ {
|
||||
if aa[i] != bb[i] {
|
||||
panic("assert equal failed")
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic("unknown type")
|
||||
}
|
||||
}
|
||||
|
||||
func print(a []uint64) {
|
||||
for _, x := range a {
|
||||
fmt.Printf("%016x ", x)
|
||||
}
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
func toBig(in []uint64) *big.Int {
|
||||
out := new(big.Int)
|
||||
for i := len(in) - 1; i >= 0; i-- {
|
||||
out.Lsh(out, 64)
|
||||
out.Add(out, new(big.Int).SetUint64(in[i]))
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// Functions implemented in c256_asm_*64.s
|
||||
// Montgomery multiplication modulo P256
|
||||
func c256MulOfGo(res, in1, in2 []uint64) {
|
||||
int1 := toBig(in1)
|
||||
int2 := toBig(in2)
|
||||
int1.Mul(int1, int2)
|
||||
int1.Mul(int1, rModInverseP)
|
||||
int1.Mod(int1, p)
|
||||
fromBig(res, int1)
|
||||
}
|
||||
|
||||
// Montgomery square modulo P256, repeated n times (n >= 1)
|
||||
func c256SqrOfGo(res, in []uint64, n int) {
|
||||
copy(res, in)
|
||||
for i := 0; i < n; i++ {
|
||||
c256MulOfGo(res, res, res)
|
||||
}
|
||||
}
|
||||
|
||||
// Montgomery multiplication by 1
|
||||
func c256FromMontOfGo(res, in []uint64) {
|
||||
int1 := toBig(in)
|
||||
int1.Mul(int1, rModInverseP)
|
||||
int1.Mod(int1, p)
|
||||
fromBig(res, int1)
|
||||
}
|
||||
|
||||
// iff cond == 1 val <- -val
|
||||
func c256NegCondOfGo(val []uint64, cond int) {
|
||||
if cond == 1 {
|
||||
int1 := toBig(val)
|
||||
int1.Sub(p, int1)
|
||||
|
||||
int1.Mod(int1, p)
|
||||
fromBig(val, int1)
|
||||
}
|
||||
}
|
||||
|
||||
// Montgomery multiplication modulo Ord(G)
|
||||
func c256OrdMulOfGo(res, in1, in2 []uint64) {
|
||||
int1 := toBig(in1)
|
||||
int2 := toBig(in2)
|
||||
int1.Mul(int1, int2)
|
||||
int1.Mul(int1, rModInverseN)
|
||||
int1.Mod(int1, n)
|
||||
fromBig(res, int1)
|
||||
}
|
||||
|
||||
// Montgomery square modulo Ord(G), repeated n times
|
||||
func c256OrdSqrOfGo(res, in []uint64, n int) {
|
||||
copy(res, in)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
c256OrdMulOfGo(res, res, res)
|
||||
}
|
||||
}
|
||||
|
||||
// the key step of mont-mul, res = in + p * in[0]
|
||||
// res:5, in:4
|
||||
func c256MulPOfGo(res, in []uint64) {
|
||||
int1 := toBig(in)
|
||||
r := new(big.Int)
|
||||
r.Mul(new(big.Int).SetUint64(in[0]), p)
|
||||
r.Add(r, int1)
|
||||
fromBig(res, r)
|
||||
}
|
||||
|
||||
func montReduceOfGo(res, a []uint64) {
|
||||
res1 := new(big.Int)
|
||||
a1 := toBig(a)
|
||||
res1.Mul(new(big.Int).SetUint64(a[0]), p)
|
||||
res1.Add(res1, a1)
|
||||
res1.Rsh(res1, 64)
|
||||
fromBig(res, res1)
|
||||
}
|
||||
|
||||
func randomPoint() (*big.Int, *big.Int) {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
return c256.ScalarMult(c256.Gx, c256.Gy, k.Bytes())
|
||||
}
|
||||
|
||||
// func TestMontReduceOfGo(t *testing.T) {
|
||||
// res1, res2, in1 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
// _ = res1
|
||||
// for i := 0; i < 100000000; i++ {
|
||||
// randUint64(in1)
|
||||
// // in1 = []uint64{1, 1, 1, 1}
|
||||
// montReduceOfGo(res1, in1)
|
||||
// // montReduce(res2, in1)
|
||||
// // print(res1)
|
||||
// // print(res2)
|
||||
// // assertEqualUint(res1, res2, "")
|
||||
// }
|
||||
// }
|
||||
|
||||
func BenchmarkUint64IsZero(b *testing.B) {
|
||||
scalar := []uint64{1, 2, 3, 4}
|
||||
for i := 0; i < b.N; i++ {
|
||||
scalarIsZero(scalar)
|
||||
}
|
||||
}
|
||||
func TestC256Mul(t *testing.T) {
|
||||
for i := 0; i < 1000000; i++ {
|
||||
// for {
|
||||
res1, res2, in1, in2 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
randUint64(in2)
|
||||
|
||||
c256MulOfGo(res1, in1, in2)
|
||||
c256Mul(res2, in1, in2)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
}
|
||||
|
||||
// 使用p256:
|
||||
// BenchmarkC256Mul-10 82318298 14.51 ns/op 0 B/op 0 allocs/op
|
||||
// 修改不用nist p256:
|
||||
// BenchmarkC256Mul-10 87902702 13.60 ns/op 0 B/op 0 allocs/op
|
||||
func BenchmarkC256Mul(b *testing.B) {
|
||||
res, in1, in2 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
randUint64(in2)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c256Mul(res, in1, in2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestC256SqrBasic(t *testing.T) {
|
||||
res, zero, in := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
c256Sqr(res, in, 1)
|
||||
assertEqual(res, zero)
|
||||
|
||||
pplus1 := new(big.Int).Add(p, big.NewInt(1))
|
||||
fromBig(in, pplus1)
|
||||
c256Sqr(res, in, 1)
|
||||
rInv := toBig(res)
|
||||
assertEqual(rInv, rModInverseP)
|
||||
|
||||
f32 := new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
|
||||
fromBig(in, f32)
|
||||
c256Sqr(res, in, 1)
|
||||
f32.Mul(f32, f32)
|
||||
f32.Mul(f32, rModInverseP)
|
||||
f32.Mod(f32, p)
|
||||
res2 := make([]uint64, 4)
|
||||
fromBig(res2, f32)
|
||||
assertEqual(res, res2)
|
||||
}
|
||||
|
||||
func TestC256Sqr(t *testing.T) {
|
||||
for n := 1; n < 10; n++ {
|
||||
for i := 0; i < 100000; i++ {
|
||||
res1, res2, in := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in)
|
||||
c256SqrOfGo(res1, in, n)
|
||||
c256Sqr(res2, in, n)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 使用p256:
|
||||
// BenchmarkC256Sqr-10 93287706 12.84 ns/op 0 B/op 0 allocs/op
|
||||
// 修改不用nist p256:
|
||||
// BenchmarkC256Sqr-10 87514056 11.72 ns/op 0 B/op 0 allocs/op
|
||||
func BenchmarkC256Sqr(b *testing.B) {
|
||||
res, in := make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c256Sqr(res, in, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestNegCond(t *testing.T) {
|
||||
res1, res2, in1 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
copy(res1, in1)
|
||||
copy(res2, in1)
|
||||
|
||||
c256NegCondOfGo(res1, 1)
|
||||
c256NegCond(res2, 1)
|
||||
assertEqual(res1, res2)
|
||||
c256NegCondOfGo(res1, 0)
|
||||
c256NegCond(res2, 0)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
|
||||
func TestMovCond(t *testing.T) {
|
||||
res, in1, in2 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
randUint64(in2)
|
||||
|
||||
c256MovCond(res, in1, in2, 1)
|
||||
assertEqual(res, in1)
|
||||
|
||||
c256MovCond(res, in1, in2, 0)
|
||||
assertEqual(res, in2)
|
||||
|
||||
c256MovCond(res, in1, in2, 12345)
|
||||
assertEqual(res, in1)
|
||||
}
|
||||
|
||||
func TestFromMont(t *testing.T) {
|
||||
for i := 0; i < 1000000; i++ {
|
||||
res1, res2, in1 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
c256FromMontOfGo(res1, in1)
|
||||
c256FromMont(res2, in1)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrdMul(t *testing.T) {
|
||||
for i := 0; i < 100000; i++ {
|
||||
res1, res2, in1, in2 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
randUint64(in2)
|
||||
|
||||
c256OrdMulOfGo(res1, in1, in2)
|
||||
c256OrdMul(res2, in1, in2)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestOrdSqr(t *testing.T) {
|
||||
for k := 1; k < 10; k++ {
|
||||
for i := 0; i < 10000; i++ {
|
||||
res1, res2, in1, in2 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
randUint64(in2)
|
||||
|
||||
c256OrdSqrOfGo(res1, in1, k)
|
||||
c256OrdSqr(res2, in1, k)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestOrdInverse(t *testing.T) {
|
||||
for i := 0; i < 1000; i++ {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
res1 := c256.Inverse(k)
|
||||
res2 := new(big.Int)
|
||||
res2.ModInverse(k, c256.N)
|
||||
|
||||
res1.Mul(res1, k)
|
||||
res1.Mod(res1, c256.N)
|
||||
res2.Mul(res2, k)
|
||||
res2.Mod(res2, c256.N)
|
||||
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestC256Inverse(t *testing.T) {
|
||||
for i := 0; i < 1000; i++ {
|
||||
res1, res2, in1, in2 := make([]uint64, 4), make([]uint64, 4), make([]uint64, 4), make([]uint64, 4)
|
||||
randUint64(in1)
|
||||
copy(in2, in1)
|
||||
|
||||
int1 := toBig(in1)
|
||||
|
||||
int1.ModInverse(int1, c256.P)
|
||||
int1.Lsh(int1, 256*2)
|
||||
int1.Mod(int1, c256.P)
|
||||
fromBig(res1, int1)
|
||||
|
||||
c256Inverse(res2, in2)
|
||||
assertEqual(res1, res2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointAddAffineAsmG(t *testing.T) {
|
||||
var g1, g2, g3, g c256Point
|
||||
x1 := new(big.Int).Set(c256.Gx)
|
||||
y1 := new(big.Int).Set(c256.Gy)
|
||||
x2, y2 := c256.CurveParams.Add(x1, y1, x1, y1)
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
|
||||
g1.c256PointFromAffine(c256.Gx, c256.Gy)
|
||||
g2.c256PointFromAffine(x2, y2)
|
||||
g3.c256PointFromAffine(x3, y3)
|
||||
|
||||
c256PointAddAffineAsm(g.xyz[:], g1.xyz[:], g2.xyz[:], 0, 1, 1)
|
||||
x, y := g3.c256PointToAffine()
|
||||
assertEqual(x3, x)
|
||||
assertEqual(y3, y)
|
||||
}
|
||||
|
||||
func TestPointAddAffineAsm(t *testing.T) {
|
||||
var p1, p2 c256Point
|
||||
{
|
||||
x1, y1 := randomPoint()
|
||||
x2 := bigFromBase16("4071bba1f6624b6e9ac69b7109db9cac04e5bba76fdc954ebe375dfb2af6df2a")
|
||||
y2 := bigFromBase16("fffffffb00000005fffffffc00000002fffffffd00000006fffffff900000004")
|
||||
y2.Sub(p, y2)
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
|
||||
y2.Sub(p, y2)
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
// p2.y = 1, set to p+1
|
||||
p2.xyz[4] = 0
|
||||
p2.xyz[5] = 0xffffffff00000001
|
||||
p2.xyz[6] = 0xffffffffffffffff
|
||||
p2.xyz[7] = 0xfffffffeffffffff
|
||||
|
||||
c256PointAddAffineAsm(p1.xyz[:], p1.xyz[:], p2.xyz[:], 1, 1, 1)
|
||||
x4, y4 := p1.c256PointToAffine()
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
}
|
||||
|
||||
{
|
||||
x1, y1 := randomPoint()
|
||||
x2 := bigFromBase16("4071bba1f6624b6e9ac69b7109db9cac04e5bba76fdc954ebe375dfb2af6df2a")
|
||||
y2 := bigFromBase16("fffffffb00000005fffffffc00000002fffffffd00000006fffffff900000004")
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
y2.Sub(p, y2)
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
|
||||
c256PointAddAffineAsm(p1.xyz[:], p1.xyz[:], p2.xyz[:], 1, 1, 1)
|
||||
x4, y4 := p1.c256PointToAffine()
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
}
|
||||
|
||||
for i := 0; i < 10000; i++ {
|
||||
x1, y1 := randomPoint()
|
||||
x2, y2 := randomPoint()
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
|
||||
c256PointAddAffineAsm(p1.xyz[:], p1.xyz[:], p2.xyz[:], 0, 1, 1)
|
||||
x4, y4 := p1.c256PointToAffine()
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
|
||||
y2.Sub(p, y2)
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
|
||||
c256PointAddAffineAsm(p1.xyz[:], p1.xyz[:], p2.xyz[:], 1, 1, 1)
|
||||
x4, y4 = p1.c256PointToAffine()
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func BenchmarkPointAddAffineAsm(b *testing.B) {
|
||||
var res, p1, p2 c256Point
|
||||
x1, y1 := randomPoint()
|
||||
x2, y2 := randomPoint()
|
||||
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c256PointAddAffineAsm(res.xyz[:], p1.xyz[:], p2.xyz[:], 1, 1, 1)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointAddAffineAsmSpeed(t *testing.T) {
|
||||
var res, p1, p2 c256Point
|
||||
x1, y1 := randomPoint()
|
||||
x2, y2 := randomPoint()
|
||||
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
total := 100000
|
||||
begin := time.Now()
|
||||
for i := 0; i < total; i++ {
|
||||
c256PointAddAffineAsm(res.xyz[:], p1.xyz[:], p2.xyz[:], 1, 1, 1)
|
||||
}
|
||||
elaspe := time.Since(begin)
|
||||
fmt.Println("time: ", elaspe.Milliseconds(), "ms")
|
||||
fmt.Println(float64(total) / float64(elaspe.Milliseconds()) * 1000)
|
||||
}
|
||||
|
||||
func TestPointAddAsm(t *testing.T) {
|
||||
var res, p1, p2 c256Point
|
||||
x1, y1 := randomPoint()
|
||||
x2 := new(big.Int).Set(x1)
|
||||
y2 := new(big.Int).Set(y1)
|
||||
y2.Sub(p, y2)
|
||||
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
c256PointAddAsm(res.xyz[:], p1.xyz[:], p2.xyz[:])
|
||||
x, y := res.c256PointToAffine()
|
||||
assertEqual(x, big.NewInt(0))
|
||||
assertEqual(y, big.NewInt(0))
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
|
||||
k1, _ := rand.Int(rand.Reader, c256.N)
|
||||
k2, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
x1, y1 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k1.Bytes())
|
||||
x2, y2 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k2.Bytes())
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
p2.c256PointFromAffine(x2, y2)
|
||||
c256PointAddAsm(res.xyz[:], p1.xyz[:], p2.xyz[:])
|
||||
|
||||
x4, y4 := res.c256PointToAffine()
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointDoubleAsm(t *testing.T) {
|
||||
for i := 0; i < 1000; i++ {
|
||||
var res1, res2, p1 c256Point
|
||||
k1, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
x1, y1 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k1.Bytes())
|
||||
x3, y3 := c256.CurveParams.Double(x1, y1)
|
||||
res2.c256PointFromAffine(x3, y3)
|
||||
|
||||
p1.c256PointFromAffine(x1, y1)
|
||||
c256PointDoubleAsm(res1.xyz[:], p1.xyz[:])
|
||||
|
||||
x4, y4 := res1.c256PointToAffine()
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
}
|
||||
}
|
||||
|
||||
// / test for Curve interface
|
||||
func TestIsOnCurve(t *testing.T) {
|
||||
if !c256.IsOnCurve(c256.Gx, c256.Gy) {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointAdd(t *testing.T) {
|
||||
x1, y1 := randomPoint()
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x1, y1)
|
||||
x4, y4 := c256.Add(x1, y1, x1, y1)
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
|
||||
x2 := new(big.Int).Set(x1)
|
||||
y2 := new(big.Int).Set(y1)
|
||||
y2.Sub(p, y2)
|
||||
x3, y3 = c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
x4, y4 = c256.Add(x1, y1, x2, y2)
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
k1, _ := rand.Int(rand.Reader, c256.N)
|
||||
k2, _ := rand.Int(rand.Reader, c256.N)
|
||||
x1, y1 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k1.Bytes())
|
||||
x2, y2 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k2.Bytes())
|
||||
x3, y3 := c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
x4, y4 := c256.Add(x1, y1, x2, y2)
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkPointDouble(b *testing.B) {
|
||||
x, y := randomPoint()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
// BenchmarkPointDouble-8 278118 4096 ns/op 192 B/op 4 allocs/op
|
||||
c256.Double(x, y)
|
||||
|
||||
// BenchmarkPointDouble-8 186952 6471 ns/op 3961 B/op 52 allocs/op
|
||||
// c256.CurveParams.Double(x, y)
|
||||
}
|
||||
}
|
||||
func BenchmarkPointAdd(b *testing.B) {
|
||||
x1, y1 := randomPoint()
|
||||
x2, y2 := randomPoint()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
//BenchmarkPointAdd-8 273103 4229 ns/op 192 B/op 4 allocs/op
|
||||
c256.Add(x1, y1, x2, y2)
|
||||
// c256.Add(x1, y1, x1, y1)
|
||||
|
||||
// BenchmarkPointAdd-8 175370 7210 ns/op 4881 B/op 65 allocs/op
|
||||
// c256.CurveParams.Add(x1, y1, x2, y2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointDouble(t *testing.T) {
|
||||
for i := 0; i < 10000; i++ {
|
||||
k1, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
x1, y1 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k1.Bytes())
|
||||
|
||||
x3, y3 := c256.CurveParams.Double(x1, y1)
|
||||
x4, y4 := c256.Double(x1, y1)
|
||||
|
||||
assertEqual(x3, x4)
|
||||
assertEqual(y3, y4)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalarMult(t *testing.T) {
|
||||
k := new(big.Int).Set(c256.N)
|
||||
x, y := c256.ScalarMult(c256.Gx, c256.Gy, k.Bytes())
|
||||
zero := big.NewInt(0)
|
||||
assertEqual(x, zero)
|
||||
assertEqual(y, zero)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
x1, y1 := c256.ScalarMult(c256.Gx, c256.Gy, k.Bytes())
|
||||
x2, y2 := c256.CurveParams.ScalarMult(c256.Gx, c256.Gy, k.Bytes())
|
||||
|
||||
assertEqual(x1, x2)
|
||||
assertEqual(y1, y2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalarBaseMult(t *testing.T) {
|
||||
k := new(big.Int).Add(c256.N, big.NewInt(1))
|
||||
x1, y1 := c256.ScalarBaseMult(k.Bytes())
|
||||
assertEqual(x1, c256.Gx)
|
||||
assertEqual(y1, c256.Gy)
|
||||
|
||||
for i := 0; i < 1000; i++ {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
x1, y1 := c256.ScalarBaseMult(k.Bytes())
|
||||
x2, y2 := c256.CurveParams.ScalarBaseMult(k.Bytes())
|
||||
|
||||
assertEqual(x1, x2)
|
||||
assertEqual(y1, y2)
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalarMultSpeed(t *testing.T) {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
x1, y1 := c256.ScalarMult(c256.Gx, c256.Gy, k.Bytes())
|
||||
|
||||
begin := time.Now()
|
||||
total := 100000
|
||||
for i := 0; i < total; i++ {
|
||||
c256.ScalarMult(x1, y1, k.Bytes())
|
||||
}
|
||||
elaspe := time.Since(begin)
|
||||
fmt.Println("time: ", elaspe.Milliseconds(), "ms")
|
||||
fmt.Println(float64(total) / float64(elaspe.Milliseconds()) * 1000)
|
||||
}
|
||||
|
||||
func BenchmarkScalarMultSpeed(b *testing.B) {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
x1, y1 := c256.ScalarMult(c256.Gx, c256.Gy, k.Bytes())
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c256.ScalarMult(x1, y1, k.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
func TestScalarBaseMultSpeed(t *testing.T) {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
|
||||
begin := time.Now()
|
||||
total := 100000
|
||||
for i := 0; i < total; i++ {
|
||||
c256.ScalarBaseMult(k.Bytes())
|
||||
}
|
||||
elaspe := time.Since(begin)
|
||||
fmt.Println("time: ", elaspe.Milliseconds(), "ms")
|
||||
fmt.Println(float64(total) / float64(elaspe.Milliseconds()) * 1000)
|
||||
}
|
||||
|
||||
func BenchmarkScalarBaseMultSpeed(b *testing.B) {
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
c256.ScalarBaseMult(k.Bytes())
|
||||
}
|
||||
}
|
||||
|
||||
// BenchmarkCombineMult-8 17679 64513 ns/op 320 B/op 6 allocs/op
|
||||
func BenchmarkCombineMult(b *testing.B) {
|
||||
x, y := randomPoint()
|
||||
k, _ := rand.Int(rand.Reader, c256.N)
|
||||
baseScalar := k.Bytes()
|
||||
k, _ = rand.Int(rand.Reader, c256.N)
|
||||
scalar := k.Bytes()
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
CombinedMult(x, y, baseScalar, scalar)
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoothW5(t *testing.T) {
|
||||
for i := uint(0); i < 64; i++ {
|
||||
sel, sign := boothW5(i)
|
||||
fmt.Println(i, "\t", sel, "\t", sign)
|
||||
_, _ = sel, sign
|
||||
}
|
||||
}
|
||||
|
||||
func TestBoothW6(t *testing.T) {
|
||||
for i := uint(0); i < 128; i++ {
|
||||
sel, sign := boothW6(i)
|
||||
// fmt.Println(i, "\t", sel, "\t", sign)
|
||||
_, _ = sel, sign
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func TestSelectBase(t *testing.T) {
|
||||
var t0 c256Point
|
||||
c256SelectBase(t0.xyz[0:8], c256Precomputed[0][0:], 1)
|
||||
|
||||
}
|
||||
|
||||
func TestSelect(t *testing.T) {
|
||||
var t0 c256Point
|
||||
var precomp [16 * 4 * 3]uint64
|
||||
var p = c256Point{
|
||||
xyz: [12]uint64{0x715A4589334C74C7,
|
||||
0x8FE30BBFF2660BE1,
|
||||
0x5F9904466A39C994,
|
||||
0x32C4AE2C1F198119,
|
||||
0x02DF32E52139F0A0,
|
||||
0xD0A9877CC62A4740,
|
||||
0x59BDCEE36B692153,
|
||||
0xBC3736A2F4F6779C,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0},
|
||||
}
|
||||
c256ToMont(p.xyz[:], p.xyz[:])
|
||||
c256Select(t0.xyz[:], precomp[:], 0)
|
||||
assertEqual(t0.xyz[:], make([]uint64, 12))
|
||||
equal := c256PointAddAsm(t0.xyz[:], t0.xyz[:], p.xyz[:])
|
||||
assert.Equal(t, equal, 1)
|
||||
}
|
||||
|
||||
/*
|
||||
TestBoothW5
|
||||
0 0 0
|
||||
1 1 0
|
||||
2 1 0
|
||||
3 2 0
|
||||
4 2 0
|
||||
5 3 0
|
||||
6 3 0
|
||||
7 4 0
|
||||
8 4 0
|
||||
9 5 0
|
||||
10 5 0
|
||||
11 6 0
|
||||
12 6 0
|
||||
13 7 0
|
||||
14 7 0
|
||||
15 8 0
|
||||
16 8 0
|
||||
17 9 0
|
||||
18 9 0
|
||||
19 10 0
|
||||
20 10 0
|
||||
21 11 0
|
||||
22 11 0
|
||||
23 12 0
|
||||
24 12 0
|
||||
25 13 0
|
||||
26 13 0
|
||||
27 14 0
|
||||
28 14 0
|
||||
29 15 0
|
||||
30 15 0
|
||||
31 16 0
|
||||
32 16 1
|
||||
33 15 1
|
||||
34 15 1
|
||||
35 14 1
|
||||
36 14 1
|
||||
37 13 1
|
||||
38 13 1
|
||||
39 12 1
|
||||
40 12 1
|
||||
41 11 1
|
||||
42 11 1
|
||||
43 10 1
|
||||
44 10 1
|
||||
45 9 1
|
||||
46 9 1
|
||||
47 8 1
|
||||
48 8 1
|
||||
49 7 1
|
||||
50 7 1
|
||||
51 6 1
|
||||
52 6 1
|
||||
53 5 1
|
||||
54 5 1
|
||||
55 4 1
|
||||
56 4 1
|
||||
57 3 1
|
||||
58 3 1
|
||||
59 2 1
|
||||
60 2 1
|
||||
61 1 1
|
||||
62 1 1
|
||||
63 0 1
|
||||
|
||||
*/
|
||||
|
||||
func TestPrintBaseMult(t *testing.T) {
|
||||
if false {
|
||||
for i, table := range c256Precomputed {
|
||||
for j := 0; j < 32; j++ {
|
||||
fmt.Printf("\t// [64^%d * %2d]G\n", i, j+1)
|
||||
fmt.Print("\t")
|
||||
for k := 0; k < 4; k++ {
|
||||
fmt.Printf("0x%016x", table[8*j+k])
|
||||
if k < 3 {
|
||||
fmt.Print(", ")
|
||||
} else {
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
fmt.Print("\t")
|
||||
for k := 4; k < 8; k++ {
|
||||
fmt.Printf("0x%016x", table[8*j+k])
|
||||
if k < 7 {
|
||||
fmt.Print(", ")
|
||||
} else {
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
}
|
||||
fmt.Println("\t//")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func writePoint(sb *strings.Builder, p c256Point) {
|
||||
x, y := p.c256PointToAffine()
|
||||
p.c256PointFromAffine(x, y)
|
||||
for k := 0; k < 8; k++ {
|
||||
sb.WriteString(fmt.Sprintf("0x%016x, ", p.xyz[k]))
|
||||
if k == 3 {
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
}
|
||||
sb.WriteString("\n")
|
||||
}
|
||||
|
||||
func TestBaseTable(t *testing.T) {
|
||||
var sb strings.Builder
|
||||
|
||||
const N = 8
|
||||
var G = c256Point{
|
||||
xyz: [12]uint64{0x715A4589334C74C7,
|
||||
0x8FE30BBFF2660BE1,
|
||||
0x5F9904466A39C994,
|
||||
0x32C4AE2C1F198119,
|
||||
0x02DF32E52139F0A0,
|
||||
0xD0A9877CC62A4740,
|
||||
0x59BDCEE36B692153,
|
||||
0xBC3736A2F4F6779C,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0},
|
||||
}
|
||||
c256ToMont(G.xyz[:4], G.xyz[:4])
|
||||
c256ToMont(G.xyz[4:], G.xyz[4:])
|
||||
c256ToMont(G.xyz[8:], G.xyz[8:])
|
||||
|
||||
var P, Q c256Point
|
||||
P = G
|
||||
for i := 0; i < 256/N; i++ {
|
||||
Q = P
|
||||
|
||||
// P
|
||||
sb.WriteString(fmt.Sprintf("// [%d^%d]G\n", 1<<N, i))
|
||||
writePoint(&sb, Q)
|
||||
|
||||
// 2P
|
||||
c256PointDoubleAsm(Q.xyz[:], Q.xyz[:])
|
||||
sb.WriteString(fmt.Sprintf("// [2 * %d^%d]G\n", 1<<N, i))
|
||||
writePoint(&sb, Q)
|
||||
|
||||
for j := 3; j <= (1 << (N - 1)); j++ {
|
||||
// jP
|
||||
c256PointAddAsm(Q.xyz[:], Q.xyz[:], P.xyz[:])
|
||||
|
||||
sb.WriteString(fmt.Sprintf("// [%d * %d^%d]G\n", j, 1<<N, i))
|
||||
writePoint(&sb, Q)
|
||||
}
|
||||
// the last round
|
||||
if i == 256/N-1 {
|
||||
for j := (1 << (N - 1)) + 1; j <= (1 << N); j++ {
|
||||
c256PointAddAsm(Q.xyz[:], Q.xyz[:], P.xyz[:])
|
||||
sb.WriteString(fmt.Sprintf("// [%d * %d^%d]G\n", j, 1<<N, i))
|
||||
writePoint(&sb, Q)
|
||||
}
|
||||
}
|
||||
c256PointDoubleAsm(P.xyz[:], Q.xyz[:])
|
||||
}
|
||||
|
||||
os.WriteFile("/Users/fengwd/Files/Codes/go/src/xdx.jelly/xgcl/sm/sm2/tbl.txt", []byte(sb.String()), 0666)
|
||||
}
|
||||
|
||||
func TestBaseTable3(t *testing.T) {
|
||||
var G = c256Point{
|
||||
xyz: [12]uint64{0x715A4589334C74C7,
|
||||
0x8FE30BBFF2660BE1,
|
||||
0x5F9904466A39C994,
|
||||
0x32C4AE2C1F198119,
|
||||
0x02DF32E52139F0A0,
|
||||
0xD0A9877CC62A4740,
|
||||
0x59BDCEE36B692153,
|
||||
0xBC3736A2F4F6779C,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0},
|
||||
}
|
||||
c256ToMont(G.xyz[:4], G.xyz[:4])
|
||||
c256ToMont(G.xyz[4:], G.xyz[4:])
|
||||
c256ToMont(G.xyz[8:], G.xyz[8:])
|
||||
|
||||
scalarReversed := []uint64{0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF}
|
||||
var r, P c256Point
|
||||
P.c256BaseMult(scalarReversed)
|
||||
c256PointAddAsm(r.xyz[:], P.xyz[:], G.xyz[:])
|
||||
x, y := r.c256PointToAffine()
|
||||
r.c256PointFromAffine(x, y)
|
||||
|
||||
for k := 0; k < 8; k++ {
|
||||
fmt.Printf("0x%016x, ", r.xyz[k])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user