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

619
integration_test.go Normal file
View File

@@ -0,0 +1,619 @@
package p256k1
import (
"crypto/rand"
"testing"
)
// Test complete ECDSA signing and verification workflow
func TestECDSASignVerifyWorkflow(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Generate a random secret key
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
// Create public key
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey[:]) {
t.Fatal("Failed to create public key")
}
// Create message hash
var msghash [32]byte
_, err = rand.Read(msghash[:])
if err != nil {
t.Fatalf("Failed to generate message hash: %v", err)
}
// Sign the message
var sig Signature
if !ECDSASign(ctx, &sig, msghash[:], seckey[:], nil, nil) {
t.Fatal("Failed to sign message")
}
// Verify the signature
if !ECDSAVerify(ctx, &sig, msghash[:], &pubkey) {
t.Fatal("Failed to verify signature")
}
// Test that signature fails with wrong message
msghash[0] ^= 1 // Flip one bit
if ECDSAVerify(ctx, &sig, msghash[:], &pubkey) {
t.Error("Signature should not verify with modified message")
}
// Restore message and test with wrong public key
msghash[0] ^= 1 // Restore original message
var wrongSeckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(wrongSeckey[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, wrongSeckey[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid wrong secret key after 10 attempts")
}
}
var wrongPubkey PublicKey
if !ECPubkeyCreate(ctx, &wrongPubkey, wrongSeckey[:]) {
t.Fatal("Failed to create wrong public key")
}
if ECDSAVerify(ctx, &sig, msghash[:], &wrongPubkey) {
t.Error("Signature should not verify with wrong public key")
}
}
// Test signature serialization and parsing
func TestSignatureSerialization(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Create a signature
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
var msghash [32]byte
_, err = rand.Read(msghash[:])
if err != nil {
t.Fatalf("Failed to generate message hash: %v", err)
}
var sig Signature
if !ECDSASign(ctx, &sig, msghash[:], seckey[:], nil, nil) {
t.Fatal("Failed to sign message")
}
// Test compact serialization
var compact [64]byte
if !ECDSASignatureSerializeCompact(ctx, compact[:], &sig) {
t.Fatal("Failed to serialize signature in compact format")
}
// Parse back from compact format
var parsedSig Signature
if !ECDSASignatureParseCompact(ctx, &parsedSig, compact[:]) {
t.Fatal("Failed to parse signature from compact format")
}
// Serialize again and compare
var compact2 [64]byte
if !ECDSASignatureSerializeCompact(ctx, compact2[:], &parsedSig) {
t.Fatal("Failed to serialize parsed signature")
}
for i := 0; i < 64; i++ {
if compact[i] != compact2[i] {
t.Error("Compact serialization round-trip failed")
break
}
}
// Test DER serialization
var der [72]byte // Max DER size
derLen := 72
if !ECDSASignatureSerializeDER(ctx, der[:], &derLen, &sig) {
t.Fatal("Failed to serialize signature in DER format")
}
// Parse back from DER format
var parsedSigDER Signature
if !ECDSASignatureParseDER(ctx, &parsedSigDER, der[:derLen]) {
t.Fatal("Failed to parse signature from DER format")
}
// Verify both parsed signatures work
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey[:]) {
t.Fatal("Failed to create public key")
}
if !ECDSAVerify(ctx, &parsedSig, msghash[:], &pubkey) {
t.Error("Parsed compact signature should verify")
}
if !ECDSAVerify(ctx, &parsedSigDER, msghash[:], &pubkey) {
t.Error("Parsed DER signature should verify")
}
}
// Test public key serialization and parsing
func TestPublicKeySerialization(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Create a public key
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey[:]) {
t.Fatal("Failed to create public key")
}
// Test compressed serialization
var compressed [33]byte
compressedLen := 33
if !ECPubkeySerialize(ctx, compressed[:], &compressedLen, &pubkey, ECCompressed) {
t.Fatal("Failed to serialize public key in compressed format")
}
if compressedLen != 33 {
t.Errorf("Expected compressed length 33, got %d", compressedLen)
}
// Test uncompressed serialization
var uncompressed [65]byte
uncompressedLen := 65
if !ECPubkeySerialize(ctx, uncompressed[:], &uncompressedLen, &pubkey, ECUncompressed) {
t.Fatal("Failed to serialize public key in uncompressed format")
}
if uncompressedLen != 65 {
t.Errorf("Expected uncompressed length 65, got %d", uncompressedLen)
}
// Parse compressed format
var parsedCompressed PublicKey
if !ECPubkeyParse(ctx, &parsedCompressed, compressed[:compressedLen]) {
t.Fatal("Failed to parse compressed public key")
}
// Parse uncompressed format
var parsedUncompressed PublicKey
if !ECPubkeyParse(ctx, &parsedUncompressed, uncompressed[:uncompressedLen]) {
t.Fatal("Failed to parse uncompressed public key")
}
// Both should represent the same key
var compressedAgain [33]byte
compressedAgainLen := 33
if !ECPubkeySerialize(ctx, compressedAgain[:], &compressedAgainLen, &parsedCompressed, ECCompressed) {
t.Fatal("Failed to serialize parsed compressed key")
}
var uncompressedAgain [33]byte
uncompressedAgainLen := 33
if !ECPubkeySerialize(ctx, uncompressedAgain[:], &uncompressedAgainLen, &parsedUncompressed, ECCompressed) {
t.Fatal("Failed to serialize parsed uncompressed key")
}
for i := 0; i < 33; i++ {
if compressedAgain[i] != uncompressedAgain[i] {
t.Error("Compressed and uncompressed should represent same key")
break
}
}
}
// Test public key comparison
func TestPublicKeyComparison(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Create two different keys
var seckey1, seckey2 [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey1[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey1[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key 1 after 10 attempts")
}
}
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey2[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey2[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key 2 after 10 attempts")
}
}
var pubkey1, pubkey2, pubkey1Copy PublicKey
if !ECPubkeyCreate(ctx, &pubkey1, seckey1[:]) {
t.Fatal("Failed to create public key 1")
}
if !ECPubkeyCreate(ctx, &pubkey2, seckey2[:]) {
t.Fatal("Failed to create public key 2")
}
if !ECPubkeyCreate(ctx, &pubkey1Copy, seckey1[:]) {
t.Fatal("Failed to create public key 1 copy")
}
// Test comparison
cmp1vs2 := ECPubkeyCmp(ctx, &pubkey1, &pubkey2)
cmp2vs1 := ECPubkeyCmp(ctx, &pubkey2, &pubkey1)
cmp1vs1 := ECPubkeyCmp(ctx, &pubkey1, &pubkey1Copy)
if cmp1vs2 == 0 {
t.Error("Different keys should not compare equal")
}
if cmp2vs1 == 0 {
t.Error("Different keys should not compare equal (reversed)")
}
if cmp1vs1 != 0 {
t.Error("Same keys should compare equal")
}
if (cmp1vs2 > 0) == (cmp2vs1 > 0) {
t.Error("Comparison should be antisymmetric")
}
}
// Test context randomization
func TestContextRandomization(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Test randomization with random seed
var seed [32]byte
_, err = rand.Read(seed[:])
if err != nil {
t.Fatalf("Failed to generate random seed: %v", err)
}
err = ContextRandomize(ctx, seed[:])
if err != nil {
t.Errorf("Context randomization failed: %v", err)
}
// Test that randomized context still works
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey[:]) {
t.Error("Key generation should work with randomized context")
}
// Test signing with randomized context
var msghash [32]byte
_, err = rand.Read(msghash[:])
if err != nil {
t.Fatalf("Failed to generate message hash: %v", err)
}
var sig Signature
if !ECDSASign(ctx, &sig, msghash[:], seckey[:], nil, nil) {
t.Error("Signing should work with randomized context")
}
if !ECDSAVerify(ctx, &sig, msghash[:], &pubkey) {
t.Error("Verification should work with randomized context")
}
// Test randomization with nil seed (should work)
err = ContextRandomize(ctx, nil)
if err != nil {
t.Errorf("Context randomization with nil seed failed: %v", err)
}
}
// Test multiple signatures with same key
func TestMultipleSignatures(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Generate key pair
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
t.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
t.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey[:]) {
t.Fatal("Failed to create public key")
}
// Sign multiple different messages
numMessages := 10
messages := make([][32]byte, numMessages)
signatures := make([]Signature, numMessages)
for i := 0; i < numMessages; i++ {
_, err = rand.Read(messages[i][:])
if err != nil {
t.Fatalf("Failed to generate message %d: %v", i, err)
}
if !ECDSASign(ctx, &signatures[i], messages[i][:], seckey[:], nil, nil) {
t.Fatalf("Failed to sign message %d", i)
}
}
// Verify all signatures
for i := 0; i < numMessages; i++ {
if !ECDSAVerify(ctx, &signatures[i], messages[i][:], &pubkey) {
t.Errorf("Failed to verify signature %d", i)
}
// Test cross-verification (should fail)
for j := 0; j < numMessages; j++ {
if i != j {
if ECDSAVerify(ctx, &signatures[i], messages[j][:], &pubkey) {
t.Errorf("Signature %d should not verify message %d", i, j)
}
}
}
}
}
// Test edge cases and error conditions
func TestEdgeCases(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Test invalid secret keys
var zeroKey [32]byte // All zeros
if ECSecKeyVerify(ctx, zeroKey[:]) {
t.Error("Zero secret key should be invalid")
}
var overflowKey [32]byte
// Set to group order (invalid)
overflowBytes := []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, 0x41,
}
copy(overflowKey[:], overflowBytes)
if ECSecKeyVerify(ctx, overflowKey[:]) {
t.Error("Overflowing secret key should be invalid")
}
// Test invalid public key parsing
var invalidPubkey PublicKey
invalidBytes := []byte{0xFF, 0xFF, 0xFF} // Too short
if ECPubkeyParse(ctx, &invalidPubkey, invalidBytes) {
t.Error("Invalid public key bytes should not parse")
}
// Test invalid signature parsing
var invalidSig Signature
invalidSigBytes := make([]byte, 64)
for i := range invalidSigBytes {
invalidSigBytes[i] = 0xFF // All 0xFF (likely invalid)
}
if ECDSASignatureParseCompact(ctx, &invalidSig, invalidSigBytes) {
// This might succeed depending on implementation, so we just test it doesn't crash
}
}
// Test selftest functionality
func TestSelftest(t *testing.T) {
if err := Selftest(); err != nil {
t.Errorf("Selftest failed: %v", err)
}
}
// Integration test with known test vectors
func TestKnownTestVectors(t *testing.T) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
t.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Test vector from Bitcoin Core tests
seckey := []byte{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
}
if !ECSecKeyVerify(ctx, seckey) {
t.Fatal("Test vector secret key should be valid")
}
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey) {
t.Fatal("Failed to create public key from test vector")
}
// Serialize and check against expected value
var serialized [33]byte
serializedLen := 33
if !ECPubkeySerialize(ctx, serialized[:], &serializedLen, &pubkey, ECCompressed) {
t.Fatal("Failed to serialize test vector public key")
}
// The expected compressed public key for secret key 1
expected := []byte{
0x02, 0x79, 0xBE, 0x66, 0x7E, 0xF9, 0xDC, 0xBB,
0xAC, 0x55, 0xA0, 0x62, 0x95, 0xCE, 0x87, 0x0B,
0x07, 0x02, 0x9B, 0xFC, 0xDB, 0x2D, 0xCE, 0x28,
0xD9, 0x59, 0xF2, 0x81, 0x5B, 0x16, 0xF8, 0x17,
0x98,
}
for i := 0; i < 33; i++ {
if serialized[i] != expected[i] {
t.Errorf("Public key mismatch at byte %d: expected %02x, got %02x", i, expected[i], serialized[i])
}
}
}
// Benchmark integration tests
func BenchmarkFullECDSAWorkflow(b *testing.B) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
b.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Pre-generate key and message
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
b.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
b.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
var pubkey PublicKey
if !ECPubkeyCreate(ctx, &pubkey, seckey[:]) {
b.Fatal("Failed to create public key")
}
var msghash [32]byte
rand.Read(msghash[:])
b.ResetTimer()
for i := 0; i < b.N; i++ {
var sig Signature
if !ECDSASign(ctx, &sig, msghash[:], seckey[:], nil, nil) {
b.Fatal("Failed to sign")
}
if !ECDSAVerify(ctx, &sig, msghash[:], &pubkey) {
b.Fatal("Failed to verify")
}
}
}
func BenchmarkKeyGeneration(b *testing.B) {
ctx, err := ContextCreate(ContextNone)
if err != nil {
b.Fatalf("Failed to create context: %v", err)
}
defer ContextDestroy(ctx)
// Pre-generate valid secret key
var seckey [32]byte
for i := 0; i < 10; i++ {
_, err = rand.Read(seckey[:])
if err != nil {
b.Fatalf("Failed to generate random bytes: %v", err)
}
if ECSecKeyVerify(ctx, seckey[:]) {
break
}
if i == 9 {
b.Fatal("Failed to generate valid secret key after 10 attempts")
}
}
var pubkey PublicKey
b.ResetTimer()
for i := 0; i < b.N; i++ {
ECPubkeyCreate(ctx, &pubkey, seckey[:])
}
}