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:
2025-11-01 19:10:34 +00:00
parent f44b16bae5
commit cf2fed8edf
28 changed files with 5680 additions and 876 deletions

View 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[:])
}
}