Remove deprecated files and update README to reflect current implementation status and features. This commit deletes unused context, ecmult, and test files, streamlining the codebase. The README has been revised to include architectural details, performance benchmarks, and security considerations for the secp256k1 implementation.
This commit is contained in:
483
ecmult_comprehensive_test.go
Normal file
483
ecmult_comprehensive_test.go
Normal file
@@ -0,0 +1,483 @@
|
||||
package p256k1
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestEcmultGen(t *testing.T) {
|
||||
ctx, err := ContextCreate(ContextNone)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create context: %v", err)
|
||||
}
|
||||
defer ContextDestroy(ctx)
|
||||
|
||||
// Test multiplication by zero
|
||||
var zero Scalar
|
||||
zero.setInt(0)
|
||||
var result GroupElementJacobian
|
||||
ecmultGen(&ctx.ecmultGenCtx, &result, &zero)
|
||||
|
||||
if !result.isInfinity() {
|
||||
t.Error("0 * G should be infinity")
|
||||
}
|
||||
|
||||
// Test multiplication by one
|
||||
var one Scalar
|
||||
one.setInt(1)
|
||||
ecmultGen(&ctx.ecmultGenCtx, &result, &one)
|
||||
|
||||
if result.isInfinity() {
|
||||
t.Error("1 * G should not be infinity")
|
||||
}
|
||||
|
||||
// Convert to affine and compare with generator
|
||||
var resultAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
|
||||
if !resultAffine.equal(&GeneratorAffine) {
|
||||
t.Error("1 * G should equal the generator point")
|
||||
}
|
||||
|
||||
// Test multiplication by two
|
||||
var two Scalar
|
||||
two.setInt(2)
|
||||
ecmultGen(&ctx.ecmultGenCtx, &result, &two)
|
||||
|
||||
// Should equal G + G
|
||||
var doubled GroupElementJacobian
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&GeneratorAffine)
|
||||
doubled.double(&genJ)
|
||||
|
||||
var resultAffine2, doubledAffine GroupElementAffine
|
||||
resultAffine2.setGEJ(&result)
|
||||
doubledAffine.setGEJ(&doubled)
|
||||
|
||||
if !resultAffine2.equal(&doubledAffine) {
|
||||
t.Error("2 * G should equal G + G")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultGenRandomScalars(t *testing.T) {
|
||||
ctx, err := ContextCreate(ContextNone)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create context: %v", err)
|
||||
}
|
||||
defer ContextDestroy(ctx)
|
||||
|
||||
// Test with random scalars
|
||||
for i := 0; i < 20; i++ {
|
||||
var bytes [32]byte
|
||||
rand.Read(bytes[:])
|
||||
bytes[0] &= 0x7F // Ensure no overflow
|
||||
|
||||
var scalar Scalar
|
||||
scalar.setB32(bytes[:])
|
||||
|
||||
if scalar.isZero() {
|
||||
continue // Skip zero
|
||||
}
|
||||
|
||||
var result GroupElementJacobian
|
||||
ecmultGen(&ctx.ecmultGenCtx, &result, &scalar)
|
||||
|
||||
if result.isInfinity() {
|
||||
t.Errorf("Random scalar %d should not produce infinity", i)
|
||||
}
|
||||
|
||||
// Test that different scalars produce different results
|
||||
var scalar2 Scalar
|
||||
scalar2.setInt(1)
|
||||
scalar2.add(&scalar, &scalar2) // scalar + 1
|
||||
|
||||
var result2 GroupElementJacobian
|
||||
ecmultGen(&ctx.ecmultGenCtx, &result2, &scalar2)
|
||||
|
||||
var resultAffine, result2Affine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
result2Affine.setGEJ(&result2)
|
||||
|
||||
if resultAffine.equal(&result2Affine) {
|
||||
t.Errorf("Different scalars should produce different points (test %d)", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultConst(t *testing.T) {
|
||||
// Test constant-time scalar multiplication
|
||||
var point GroupElementAffine
|
||||
point = GeneratorAffine
|
||||
|
||||
// Test multiplication by zero
|
||||
var zero Scalar
|
||||
zero.setInt(0)
|
||||
var result GroupElementJacobian
|
||||
EcmultConst(&result, &zero, &point)
|
||||
|
||||
if !result.isInfinity() {
|
||||
t.Error("0 * P should be infinity")
|
||||
}
|
||||
|
||||
// Test multiplication by one
|
||||
var one Scalar
|
||||
one.setInt(1)
|
||||
EcmultConst(&result, &one, &point)
|
||||
|
||||
var resultAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
|
||||
if !resultAffine.equal(&point) {
|
||||
t.Error("1 * P should equal P")
|
||||
}
|
||||
|
||||
// Test multiplication by two
|
||||
var two Scalar
|
||||
two.setInt(2)
|
||||
EcmultConst(&result, &two, &point)
|
||||
|
||||
// Should equal P + P
|
||||
var pointJ GroupElementJacobian
|
||||
pointJ.setGE(&point)
|
||||
var doubled GroupElementJacobian
|
||||
doubled.double(&pointJ)
|
||||
|
||||
var doubledAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
doubledAffine.setGEJ(&doubled)
|
||||
|
||||
if !resultAffine.equal(&doubledAffine) {
|
||||
t.Error("2 * P should equal P + P")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultConstVsGen(t *testing.T) {
|
||||
// Test that EcmultConst with generator gives same result as EcmultGen
|
||||
ctx, err := ContextCreate(ContextNone)
|
||||
if err != nil {
|
||||
t.Fatalf("Failed to create context: %v", err)
|
||||
}
|
||||
defer ContextDestroy(ctx)
|
||||
|
||||
for i := 1; i <= 10; i++ {
|
||||
var scalar Scalar
|
||||
scalar.setInt(uint(i))
|
||||
|
||||
// Use EcmultGen
|
||||
var resultGen GroupElementJacobian
|
||||
ecmultGen(&ctx.ecmultGenCtx, &resultGen, &scalar)
|
||||
|
||||
// Use EcmultConst with generator
|
||||
var resultConst GroupElementJacobian
|
||||
EcmultConst(&resultConst, &scalar, &GeneratorAffine)
|
||||
|
||||
// Convert to affine for comparison
|
||||
var genAffine, constAffine GroupElementAffine
|
||||
genAffine.setGEJ(&resultGen)
|
||||
constAffine.setGEJ(&resultConst)
|
||||
|
||||
if !genAffine.equal(&constAffine) {
|
||||
t.Errorf("EcmultGen and EcmultConst should give same result for scalar %d", i)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultMulti(t *testing.T) {
|
||||
// Test multi-scalar multiplication
|
||||
var points [3]*GroupElementAffine
|
||||
var scalars [3]*Scalar
|
||||
|
||||
// Initialize test data
|
||||
for i := 0; i < 3; i++ {
|
||||
points[i] = &GroupElementAffine{}
|
||||
*points[i] = GeneratorAffine
|
||||
|
||||
scalars[i] = &Scalar{}
|
||||
scalars[i].setInt(uint(i + 1))
|
||||
}
|
||||
|
||||
var result GroupElementJacobian
|
||||
EcmultMulti(&result, scalars[:], points[:])
|
||||
|
||||
if result.isInfinity() {
|
||||
t.Error("Multi-scalar multiplication should not result in infinity for non-zero inputs")
|
||||
}
|
||||
|
||||
// Verify result equals sum of individual multiplications
|
||||
var expected GroupElementJacobian
|
||||
expected.setInfinity()
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
var individual GroupElementJacobian
|
||||
EcmultConst(&individual, scalars[i], points[i])
|
||||
expected.addVar(&expected, &individual)
|
||||
}
|
||||
|
||||
var resultAffine, expectedAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
expectedAffine.setGEJ(&expected)
|
||||
|
||||
if !resultAffine.equal(&expectedAffine) {
|
||||
t.Error("Multi-scalar multiplication should equal sum of individual multiplications")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultMultiEdgeCases(t *testing.T) {
|
||||
// Test with empty arrays
|
||||
var result GroupElementJacobian
|
||||
EcmultMulti(&result, nil, nil)
|
||||
|
||||
if !result.isInfinity() {
|
||||
t.Error("Multi-scalar multiplication with empty arrays should be infinity")
|
||||
}
|
||||
|
||||
// Test with single element
|
||||
var points [1]*GroupElementAffine
|
||||
var scalars [1]*Scalar
|
||||
|
||||
points[0] = &GeneratorAffine
|
||||
scalars[0] = &Scalar{}
|
||||
scalars[0].setInt(5)
|
||||
|
||||
EcmultMulti(&result, scalars[:], points[:])
|
||||
|
||||
// Should equal 5 * G
|
||||
var expected GroupElementJacobian
|
||||
EcmultConst(&expected, scalars[0], points[0])
|
||||
|
||||
var resultAffine, expectedAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
expectedAffine.setGEJ(&expected)
|
||||
|
||||
if !resultAffine.equal(&expectedAffine) {
|
||||
t.Error("Single-element multi-scalar multiplication should equal individual multiplication")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultMultiWithZeros(t *testing.T) {
|
||||
// Test multi-scalar multiplication with some zero scalars
|
||||
var points [3]*GroupElementAffine
|
||||
var scalars [3]*Scalar
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
points[i] = &GroupElementAffine{}
|
||||
*points[i] = GeneratorAffine
|
||||
|
||||
scalars[i] = &Scalar{}
|
||||
if i == 1 {
|
||||
scalars[i].setInt(0) // Middle scalar is zero
|
||||
} else {
|
||||
scalars[i].setInt(uint(i + 1))
|
||||
}
|
||||
}
|
||||
|
||||
var result GroupElementJacobian
|
||||
EcmultMulti(&result, scalars[:], points[:])
|
||||
|
||||
// Should equal 1*G + 0*G + 3*G = 1*G + 3*G = 4*G
|
||||
var expected GroupElementJacobian
|
||||
var four Scalar
|
||||
four.setInt(4)
|
||||
EcmultConst(&expected, &four, &GeneratorAffine)
|
||||
|
||||
var resultAffine, expectedAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
expectedAffine.setGEJ(&expected)
|
||||
|
||||
if !resultAffine.equal(&expectedAffine) {
|
||||
t.Error("Multi-scalar multiplication with zeros should skip zero terms")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultProperties(t *testing.T) {
|
||||
// Test linearity: k1*P + k2*P = (k1 + k2)*P
|
||||
var k1, k2, sum Scalar
|
||||
k1.setInt(7)
|
||||
k2.setInt(11)
|
||||
sum.add(&k1, &k2)
|
||||
|
||||
var result1, result2, resultSum GroupElementJacobian
|
||||
EcmultConst(&result1, &k1, &GeneratorAffine)
|
||||
EcmultConst(&result2, &k2, &GeneratorAffine)
|
||||
EcmultConst(&resultSum, &sum, &GeneratorAffine)
|
||||
|
||||
// result1 + result2 should equal resultSum
|
||||
var combined GroupElementJacobian
|
||||
combined.addVar(&result1, &result2)
|
||||
|
||||
var combinedAffine, sumAffine GroupElementAffine
|
||||
combinedAffine.setGEJ(&combined)
|
||||
sumAffine.setGEJ(&resultSum)
|
||||
|
||||
if !combinedAffine.equal(&sumAffine) {
|
||||
t.Error("Linearity property should hold: k1*P + k2*P = (k1 + k2)*P")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultDistributivity(t *testing.T) {
|
||||
// Test distributivity: k*(P + Q) = k*P + k*Q
|
||||
var k Scalar
|
||||
k.setInt(5)
|
||||
|
||||
// Create two different points
|
||||
var p, q GroupElementAffine
|
||||
p = GeneratorAffine
|
||||
|
||||
var two Scalar
|
||||
two.setInt(2)
|
||||
var qJ GroupElementJacobian
|
||||
EcmultConst(&qJ, &two, &p) // Q = 2*P
|
||||
q.setGEJ(&qJ)
|
||||
|
||||
// Compute P + Q
|
||||
var pJ GroupElementJacobian
|
||||
pJ.setGE(&p)
|
||||
var pPlusQJ GroupElementJacobian
|
||||
pPlusQJ.addGE(&pJ, &q)
|
||||
var pPlusQ GroupElementAffine
|
||||
pPlusQ.setGEJ(&pPlusQJ)
|
||||
|
||||
// Compute k*(P + Q)
|
||||
var leftSide GroupElementJacobian
|
||||
EcmultConst(&leftSide, &k, &pPlusQ)
|
||||
|
||||
// Compute k*P + k*Q
|
||||
var kP, kQ GroupElementJacobian
|
||||
EcmultConst(&kP, &k, &p)
|
||||
EcmultConst(&kQ, &k, &q)
|
||||
var rightSide GroupElementJacobian
|
||||
rightSide.addVar(&kP, &kQ)
|
||||
|
||||
var leftAffine, rightAffine GroupElementAffine
|
||||
leftAffine.setGEJ(&leftSide)
|
||||
rightAffine.setGEJ(&rightSide)
|
||||
|
||||
if !leftAffine.equal(&rightAffine) {
|
||||
t.Error("Distributivity should hold: k*(P + Q) = k*P + k*Q")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultLargeScalars(t *testing.T) {
|
||||
// Test with large scalars (close to group order)
|
||||
var largeScalar Scalar
|
||||
largeBytes := [32]byte{
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE,
|
||||
0xBA, 0xAE, 0xDC, 0xE6, 0xAF, 0x48, 0xA0, 0x3B,
|
||||
0xBF, 0xD2, 0x5E, 0x8C, 0xD0, 0x36, 0x41, 0x40,
|
||||
} // n - 1
|
||||
largeScalar.setB32(largeBytes[:])
|
||||
|
||||
var result GroupElementJacobian
|
||||
EcmultConst(&result, &largeScalar, &GeneratorAffine)
|
||||
|
||||
if result.isInfinity() {
|
||||
t.Error("(n-1) * G should not be infinity")
|
||||
}
|
||||
|
||||
// (n-1) * G + G should equal infinity (since n * G = infinity)
|
||||
var genJ GroupElementJacobian
|
||||
genJ.setGE(&GeneratorAffine)
|
||||
result.addVar(&result, &genJ)
|
||||
|
||||
if !result.isInfinity() {
|
||||
t.Error("(n-1) * G + G should equal infinity")
|
||||
}
|
||||
}
|
||||
|
||||
func TestEcmultNegativeScalars(t *testing.T) {
|
||||
// Test with negative scalars (using negation)
|
||||
var k Scalar
|
||||
k.setInt(7)
|
||||
|
||||
var negK Scalar
|
||||
negK.negate(&k)
|
||||
|
||||
var result, negResult GroupElementJacobian
|
||||
EcmultConst(&result, &k, &GeneratorAffine)
|
||||
EcmultConst(&negResult, &negK, &GeneratorAffine)
|
||||
|
||||
// negResult should be the negation of result
|
||||
var negResultNegated GroupElementJacobian
|
||||
negResultNegated.negate(&negResult)
|
||||
|
||||
var resultAffine, negatedAffine GroupElementAffine
|
||||
resultAffine.setGEJ(&result)
|
||||
negatedAffine.setGEJ(&negResultNegated)
|
||||
|
||||
if !resultAffine.equal(&negatedAffine) {
|
||||
t.Error("(-k) * P should equal -(k * P)")
|
||||
}
|
||||
}
|
||||
|
||||
// Benchmark tests
|
||||
func BenchmarkEcmultGen(b *testing.B) {
|
||||
ctx, err := ContextCreate(ContextNone)
|
||||
if err != nil {
|
||||
b.Fatalf("Failed to create context: %v", err)
|
||||
}
|
||||
defer ContextDestroy(ctx)
|
||||
|
||||
var scalar Scalar
|
||||
scalar.setInt(12345)
|
||||
var result GroupElementJacobian
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
ecmultGen(&ctx.ecmultGenCtx, &result, &scalar)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEcmultConst(b *testing.B) {
|
||||
var point GroupElementAffine
|
||||
point = GeneratorAffine
|
||||
|
||||
var scalar Scalar
|
||||
scalar.setInt(12345)
|
||||
var result GroupElementJacobian
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
EcmultConst(&result, &scalar, &point)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEcmultMulti3Points(b *testing.B) {
|
||||
var points [3]*GroupElementAffine
|
||||
var scalars [3]*Scalar
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
points[i] = &GroupElementAffine{}
|
||||
*points[i] = GeneratorAffine
|
||||
|
||||
scalars[i] = &Scalar{}
|
||||
scalars[i].setInt(uint(i + 1000))
|
||||
}
|
||||
|
||||
var result GroupElementJacobian
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
EcmultMulti(&result, scalars[:], points[:])
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkEcmultMulti10Points(b *testing.B) {
|
||||
var points [10]*GroupElementAffine
|
||||
var scalars [10]*Scalar
|
||||
|
||||
for i := 0; i < 10; i++ {
|
||||
points[i] = &GroupElementAffine{}
|
||||
*points[i] = GeneratorAffine
|
||||
|
||||
scalars[i] = &Scalar{}
|
||||
scalars[i].setInt(uint(i + 1000))
|
||||
}
|
||||
|
||||
var result GroupElementJacobian
|
||||
|
||||
b.ResetTimer()
|
||||
for i := 0; i < b.N; i++ {
|
||||
EcmultMulti(&result, scalars[:], points[:])
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user