371 lines
9.8 KiB
Go
371 lines
9.8 KiB
Go
package p256k1
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
// TestSecp256k1SchnorrsigVerifyComparison tests that secp256k1_schnorrsig_verify
|
|
// produces the same results as the existing SchnorrVerify function
|
|
func TestSecp256k1SchnorrsigVerifyComparison(t *testing.T) {
|
|
// Create a context (required by secp256k1_schnorrsig_verify)
|
|
ctx := &secp256k1_context{
|
|
ecmult_gen_ctx: secp256k1_ecmult_gen_context{built: 1},
|
|
declassify: 0,
|
|
}
|
|
|
|
// Test case 1: Valid signature
|
|
t.Run("ValidSignature", func(t *testing.T) {
|
|
// Generate keypair
|
|
kp, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair: %v", err)
|
|
}
|
|
defer kp.Clear()
|
|
|
|
// Get x-only pubkey
|
|
xonly, err := kp.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey: %v", err)
|
|
}
|
|
|
|
// Create message
|
|
msg := make([]byte, 32)
|
|
for i := range msg {
|
|
msg[i] = byte(i)
|
|
}
|
|
|
|
// Sign
|
|
var sig [64]byte
|
|
if err := SchnorrSign(sig[:], msg, kp, nil); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
|
|
// Convert x-only pubkey to secp256k1_xonly_pubkey format
|
|
var secp_xonly secp256k1_xonly_pubkey
|
|
copy(secp_xonly.data[:], xonly.data[:])
|
|
|
|
// Test existing implementation (old)
|
|
existingResult := SchnorrVerifyOld(sig[:], msg, xonly)
|
|
|
|
// Test new implementation (C-translated)
|
|
newResult := SchnorrVerify(sig[:], msg, xonly)
|
|
|
|
// Compare results
|
|
if existingResult != newResult {
|
|
t.Errorf("results differ: existing=%v, new=%v", existingResult, newResult)
|
|
}
|
|
|
|
if !existingResult {
|
|
t.Error("signature verification failed (both implementations)")
|
|
}
|
|
})
|
|
|
|
// Test case 2: Invalid signature (wrong message)
|
|
t.Run("InvalidSignature_WrongMessage", func(t *testing.T) {
|
|
// Generate keypair
|
|
kp, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair: %v", err)
|
|
}
|
|
defer kp.Clear()
|
|
|
|
// Get x-only pubkey
|
|
xonly, err := kp.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey: %v", err)
|
|
}
|
|
|
|
// Create message
|
|
msg := make([]byte, 32)
|
|
for i := range msg {
|
|
msg[i] = byte(i)
|
|
}
|
|
|
|
// Sign
|
|
var sig [64]byte
|
|
if err := SchnorrSign(sig[:], msg, kp, nil); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
|
|
// Create wrong message
|
|
wrongMsg := make([]byte, 32)
|
|
copy(wrongMsg, msg)
|
|
wrongMsg[0] ^= 1
|
|
|
|
// Convert x-only pubkey to secp256k1_xonly_pubkey format
|
|
var secp_xonly secp256k1_xonly_pubkey
|
|
copy(secp_xonly.data[:], xonly.data[:])
|
|
|
|
// Test existing implementation (old)
|
|
existingResult := SchnorrVerifyOld(sig[:], wrongMsg, xonly)
|
|
|
|
// Test new implementation (C-translated)
|
|
newResult := SchnorrVerify(sig[:], wrongMsg, xonly)
|
|
|
|
// Compare results
|
|
if existingResult != newResult {
|
|
t.Errorf("results differ: existing=%v, new=%v", existingResult, newResult)
|
|
}
|
|
|
|
if existingResult {
|
|
t.Error("signature verification should fail with wrong message (both implementations)")
|
|
}
|
|
})
|
|
|
|
// Test case 3: Invalid signature (wrong signature)
|
|
t.Run("InvalidSignature_WrongSignature", func(t *testing.T) {
|
|
// Generate keypair
|
|
kp, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair: %v", err)
|
|
}
|
|
defer kp.Clear()
|
|
|
|
// Get x-only pubkey
|
|
xonly, err := kp.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey: %v", err)
|
|
}
|
|
|
|
// Create message
|
|
msg := make([]byte, 32)
|
|
for i := range msg {
|
|
msg[i] = byte(i)
|
|
}
|
|
|
|
// Sign
|
|
var sig [64]byte
|
|
if err := SchnorrSign(sig[:], msg, kp, nil); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
|
|
// Create wrong signature
|
|
wrongSig := make([]byte, 64)
|
|
copy(wrongSig, sig[:])
|
|
wrongSig[0] ^= 1
|
|
|
|
// Convert x-only pubkey to secp256k1_xonly_pubkey format
|
|
var secp_xonly secp256k1_xonly_pubkey
|
|
copy(secp_xonly.data[:], xonly.data[:])
|
|
|
|
// Test existing implementation (old)
|
|
existingResult := SchnorrVerifyOld(wrongSig, msg, xonly)
|
|
|
|
// Test new implementation (C-translated)
|
|
newResult := SchnorrVerify(wrongSig, msg, xonly)
|
|
|
|
// Compare results
|
|
if existingResult != newResult {
|
|
t.Errorf("results differ: existing=%v, new=%v", existingResult, newResult)
|
|
}
|
|
|
|
if existingResult {
|
|
t.Error("signature verification should fail with wrong signature (both implementations)")
|
|
}
|
|
})
|
|
|
|
// Test case 4: Invalid signature (wrong pubkey)
|
|
t.Run("InvalidSignature_WrongPubkey", func(t *testing.T) {
|
|
// Generate two keypairs
|
|
kp1, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair 1: %v", err)
|
|
}
|
|
defer kp1.Clear()
|
|
|
|
kp2, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair 2: %v", err)
|
|
}
|
|
defer kp2.Clear()
|
|
|
|
// Get x-only pubkey for kp2 (we sign with kp1, verify with kp2)
|
|
xonly2, err := kp2.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey 2: %v", err)
|
|
}
|
|
|
|
// Create message
|
|
msg := make([]byte, 32)
|
|
for i := range msg {
|
|
msg[i] = byte(i)
|
|
}
|
|
|
|
// Sign with keypair 1
|
|
var sig [64]byte
|
|
if err := SchnorrSign(sig[:], msg, kp1, nil); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
|
|
// Convert x-only pubkey 2 to secp256k1_xonly_pubkey format
|
|
var secp_xonly2 secp256k1_xonly_pubkey
|
|
copy(secp_xonly2.data[:], xonly2.data[:])
|
|
|
|
// Test existing implementation (old, verify with wrong pubkey)
|
|
existingResult := SchnorrVerifyOld(sig[:], msg, xonly2)
|
|
|
|
// Test new implementation (C-translated, verify with wrong pubkey)
|
|
newResult := SchnorrVerify(sig[:], msg, xonly2)
|
|
|
|
// Compare results
|
|
if existingResult != newResult {
|
|
t.Errorf("results differ: existing=%v, new=%v", existingResult, newResult)
|
|
}
|
|
|
|
if existingResult {
|
|
t.Error("signature verification should fail with wrong pubkey (both implementations)")
|
|
}
|
|
})
|
|
|
|
// Test case 5: Edge cases - nil/invalid inputs
|
|
t.Run("EdgeCases", func(t *testing.T) {
|
|
// Generate keypair
|
|
kp, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair: %v", err)
|
|
}
|
|
defer kp.Clear()
|
|
|
|
// Get x-only pubkey
|
|
xonly, err := kp.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey: %v", err)
|
|
}
|
|
|
|
msg := make([]byte, 32)
|
|
var sig [64]byte
|
|
|
|
// Test with nil context
|
|
var secp_xonly secp256k1_xonly_pubkey
|
|
copy(secp_xonly.data[:], xonly.data[:])
|
|
|
|
newResult := secp256k1_schnorrsig_verify(nil, sig[:], msg, len(msg), &secp_xonly)
|
|
if newResult != 0 {
|
|
t.Error("should return 0 with nil context")
|
|
}
|
|
|
|
// Test with nil signature
|
|
newResult = secp256k1_schnorrsig_verify(ctx, nil, msg, len(msg), &secp_xonly)
|
|
if newResult != 0 {
|
|
t.Error("should return 0 with nil signature")
|
|
}
|
|
|
|
// Test with nil pubkey
|
|
newResult = secp256k1_schnorrsig_verify(ctx, sig[:], msg, len(msg), nil)
|
|
if newResult != 0 {
|
|
t.Error("should return 0 with nil pubkey")
|
|
}
|
|
|
|
// Test with invalid signature length
|
|
if SchnorrVerify([]byte{1}, msg, xonly) {
|
|
t.Error("existing: should fail with invalid signature length")
|
|
}
|
|
newResult = secp256k1_schnorrsig_verify(ctx, []byte{1}, msg, len(msg), &secp_xonly)
|
|
if newResult != 0 {
|
|
t.Error("new: should return 0 with invalid signature length")
|
|
}
|
|
})
|
|
|
|
// Test case 6: Multiple signatures with different aux_rand
|
|
t.Run("MultipleSignatures_DifferentAuxRand", func(t *testing.T) {
|
|
// Generate keypair
|
|
kp, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair: %v", err)
|
|
}
|
|
defer kp.Clear()
|
|
|
|
// Get x-only pubkey
|
|
xonly, err := kp.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey: %v", err)
|
|
}
|
|
|
|
msg := make([]byte, 32)
|
|
|
|
// Sign with different aux_rand values
|
|
auxRand1 := make([]byte, 32)
|
|
auxRand2 := make([]byte, 32)
|
|
for i := range auxRand1 {
|
|
auxRand1[i] = byte(i)
|
|
auxRand2[i] = byte(i + 1)
|
|
}
|
|
|
|
var sig1, sig2 [64]byte
|
|
if err := SchnorrSign(sig1[:], msg, kp, auxRand1); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
if err := SchnorrSign(sig2[:], msg, kp, auxRand2); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
|
|
// Convert x-only pubkey to secp256k1_xonly_pubkey format
|
|
var secp_xonly secp256k1_xonly_pubkey
|
|
copy(secp_xonly.data[:], xonly.data[:])
|
|
|
|
// Test both signatures with existing implementation
|
|
existingResult1 := SchnorrVerify(sig1[:], msg, xonly)
|
|
existingResult2 := SchnorrVerify(sig2[:], msg, xonly)
|
|
|
|
// Test both signatures with new implementation
|
|
newResult1 := secp256k1_schnorrsig_verify(ctx, sig1[:], msg, len(msg), &secp_xonly)
|
|
newResult2 := secp256k1_schnorrsig_verify(ctx, sig2[:], msg, len(msg), &secp_xonly)
|
|
|
|
// Compare results
|
|
if existingResult1 != (newResult1 != 0) {
|
|
t.Errorf("signature 1 results differ: existing=%v, new=%d", existingResult1, newResult1)
|
|
}
|
|
if existingResult2 != (newResult2 != 0) {
|
|
t.Errorf("signature 2 results differ: existing=%v, new=%d", existingResult2, newResult2)
|
|
}
|
|
|
|
if !existingResult1 || !existingResult2 {
|
|
t.Error("both signatures should verify")
|
|
}
|
|
})
|
|
|
|
// Test case 7: Empty message
|
|
t.Run("EmptyMessage", func(t *testing.T) {
|
|
// Generate keypair
|
|
kp, err := KeyPairGenerate()
|
|
if err != nil {
|
|
t.Fatalf("failed to generate keypair: %v", err)
|
|
}
|
|
defer kp.Clear()
|
|
|
|
// Get x-only pubkey
|
|
xonly, err := kp.XOnlyPubkey()
|
|
if err != nil {
|
|
t.Fatalf("failed to get x-only pubkey: %v", err)
|
|
}
|
|
|
|
// Create 32-byte message (all zeros)
|
|
msg := make([]byte, 32)
|
|
|
|
// Sign
|
|
var sig [64]byte
|
|
if err := SchnorrSign(sig[:], msg, kp, nil); err != nil {
|
|
t.Fatalf("failed to sign: %v", err)
|
|
}
|
|
|
|
// Convert x-only pubkey to secp256k1_xonly_pubkey format
|
|
var secp_xonly secp256k1_xonly_pubkey
|
|
copy(secp_xonly.data[:], xonly.data[:])
|
|
|
|
// Test existing implementation (old)
|
|
existingResult := SchnorrVerifyOld(sig[:], msg, xonly)
|
|
|
|
// Test new implementation (C-translated)
|
|
newResult := SchnorrVerify(sig[:], msg, xonly)
|
|
|
|
// Compare results
|
|
if existingResult != newResult {
|
|
t.Errorf("results differ: existing=%v, new=%v", existingResult, newResult)
|
|
}
|
|
|
|
if !existingResult {
|
|
t.Error("signature verification failed for empty message")
|
|
}
|
|
})
|
|
}
|