//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<