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

942 lines
21 KiB
Go

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