secp_test.go raw

   1  package secp
   2  
   3  import (
   4  	"crypto/rand"
   5  	"crypto/sha256"
   6  	"testing"
   7  )
   8  
   9  func TestContextCreation(t *testing.T) {
  10  	ctx, err := NewContext(ContextSign | ContextVerify)
  11  	if err != nil {
  12  		t.Fatalf("Failed to create context: %v", err)
  13  	}
  14  	defer ctx.Destroy()
  15  
  16  	if ctx.ctx == 0 {
  17  		t.Fatal("Context handle is null")
  18  	}
  19  }
  20  
  21  func TestPublicKeyGeneration(t *testing.T) {
  22  	ctx, err := NewContext(ContextSign)
  23  	if err != nil {
  24  		t.Fatalf("Failed to create context: %v", err)
  25  	}
  26  	defer ctx.Destroy()
  27  
  28  	privKey := make([]byte, 32)
  29  	if _, err := rand.Read(privKey); err != nil {
  30  		t.Fatalf("Failed to generate random key: %v", err)
  31  	}
  32  
  33  	pubKey, err := ctx.CreatePublicKey(privKey)
  34  	if err != nil {
  35  		t.Fatalf("Failed to create public key: %v", err)
  36  	}
  37  
  38  	if len(pubKey) != PublicKeySize {
  39  		t.Fatalf("Public key size incorrect: got %d, want %d", len(pubKey), PublicKeySize)
  40  	}
  41  }
  42  
  43  func TestPublicKeySerialization(t *testing.T) {
  44  	ctx, err := NewContext(ContextSign)
  45  	if err != nil {
  46  		t.Fatalf("Failed to create context: %v", err)
  47  	}
  48  	defer ctx.Destroy()
  49  
  50  	privKey := make([]byte, 32)
  51  	if _, err := rand.Read(privKey); err != nil {
  52  		t.Fatalf("Failed to generate random key: %v", err)
  53  	}
  54  
  55  	pubKey, err := ctx.CreatePublicKey(privKey)
  56  	if err != nil {
  57  		t.Fatalf("Failed to create public key: %v", err)
  58  	}
  59  
  60  	// Test compressed
  61  	compressed, err := ctx.SerializePublicKey(pubKey, true)
  62  	if err != nil {
  63  		t.Fatalf("Failed to serialize compressed: %v", err)
  64  	}
  65  	if len(compressed) != CompressedPublicKeySize {
  66  		t.Fatalf("Compressed size incorrect: got %d, want %d", len(compressed), CompressedPublicKeySize)
  67  	}
  68  
  69  	// Test uncompressed
  70  	uncompressed, err := ctx.SerializePublicKey(pubKey, false)
  71  	if err != nil {
  72  		t.Fatalf("Failed to serialize uncompressed: %v", err)
  73  	}
  74  	if len(uncompressed) != UncompressedPublicKeySize {
  75  		t.Fatalf("Uncompressed size incorrect: got %d, want %d", len(uncompressed), UncompressedPublicKeySize)
  76  	}
  77  
  78  	// Parse back compressed
  79  	parsed, err := ctx.ParsePublicKey(compressed)
  80  	if err != nil {
  81  		t.Fatalf("Failed to parse compressed: %v", err)
  82  	}
  83  	if len(parsed) != PublicKeySize {
  84  		t.Fatalf("Parsed size incorrect: got %d, want %d", len(parsed), PublicKeySize)
  85  	}
  86  }
  87  
  88  func TestECDSASignAndVerify(t *testing.T) {
  89  	ctx, err := NewContext(ContextSign | ContextVerify)
  90  	if err != nil {
  91  		t.Fatalf("Failed to create context: %v", err)
  92  	}
  93  	defer ctx.Destroy()
  94  
  95  	privKey := make([]byte, 32)
  96  	if _, err := rand.Read(privKey); err != nil {
  97  		t.Fatalf("Failed to generate random key: %v", err)
  98  	}
  99  
 100  	pubKey, err := ctx.CreatePublicKey(privKey)
 101  	if err != nil {
 102  		t.Fatalf("Failed to create public key: %v", err)
 103  	}
 104  
 105  	message := []byte("Test message")
 106  	msgHash := sha256.Sum256(message)
 107  
 108  	sig, err := ctx.Sign(msgHash[:], privKey)
 109  	if err != nil {
 110  		t.Fatalf("Failed to sign: %v", err)
 111  	}
 112  
 113  	valid, err := ctx.Verify(msgHash[:], sig, pubKey)
 114  	if err != nil {
 115  		t.Fatalf("Failed to verify: %v", err)
 116  	}
 117  
 118  	if !valid {
 119  		t.Fatal("Signature should be valid")
 120  	}
 121  
 122  	// Test with wrong message
 123  	wrongMsg := []byte("Wrong message")
 124  	wrongHash := sha256.Sum256(wrongMsg)
 125  	valid2, err := ctx.Verify(wrongHash[:], sig, pubKey)
 126  	if err != nil {
 127  		t.Fatalf("Failed to verify wrong message: %v", err)
 128  	}
 129  
 130  	if valid2 {
 131  		t.Fatal("Signature should be invalid for wrong message")
 132  	}
 133  }
 134  
 135  func TestDERSignatureSerialization(t *testing.T) {
 136  	ctx, err := NewContext(ContextSign)
 137  	if err != nil {
 138  		t.Fatalf("Failed to create context: %v", err)
 139  	}
 140  	defer ctx.Destroy()
 141  
 142  	privKey := make([]byte, 32)
 143  	if _, err := rand.Read(privKey); err != nil {
 144  		t.Fatalf("Failed to generate random key: %v", err)
 145  	}
 146  
 147  	message := []byte("Test message")
 148  	msgHash := sha256.Sum256(message)
 149  
 150  	sig, err := ctx.Sign(msgHash[:], privKey)
 151  	if err != nil {
 152  		t.Fatalf("Failed to sign: %v", err)
 153  	}
 154  
 155  	derSig, err := ctx.SerializeSignatureDER(sig)
 156  	if err != nil {
 157  		t.Fatalf("Failed to serialize DER: %v", err)
 158  	}
 159  
 160  	parsed, err := ctx.ParseSignatureDER(derSig)
 161  	if err != nil {
 162  		t.Fatalf("Failed to parse DER: %v", err)
 163  	}
 164  
 165  	if len(parsed) != SignatureSize {
 166  		t.Fatalf("Parsed signature size incorrect: got %d, want %d", len(parsed), SignatureSize)
 167  	}
 168  }
 169  
 170  func TestCompactSignatureSerialization(t *testing.T) {
 171  	ctx, err := NewContext(ContextSign)
 172  	if err != nil {
 173  		t.Fatalf("Failed to create context: %v", err)
 174  	}
 175  	defer ctx.Destroy()
 176  
 177  	privKey := make([]byte, 32)
 178  	if _, err := rand.Read(privKey); err != nil {
 179  		t.Fatalf("Failed to generate random key: %v", err)
 180  	}
 181  
 182  	message := []byte("Test message")
 183  	msgHash := sha256.Sum256(message)
 184  
 185  	sig, err := ctx.Sign(msgHash[:], privKey)
 186  	if err != nil {
 187  		t.Fatalf("Failed to sign: %v", err)
 188  	}
 189  
 190  	compact, err := ctx.SerializeSignatureCompact(sig)
 191  	if err != nil {
 192  		t.Fatalf("Failed to serialize compact: %v", err)
 193  	}
 194  
 195  	if len(compact) != CompactSignatureSize {
 196  		t.Fatalf("Compact size incorrect: got %d, want %d", len(compact), CompactSignatureSize)
 197  	}
 198  
 199  	parsed, err := ctx.ParseSignatureCompact(compact)
 200  	if err != nil {
 201  		t.Fatalf("Failed to parse compact: %v", err)
 202  	}
 203  
 204  	if len(parsed) != SignatureSize {
 205  		t.Fatalf("Parsed signature size incorrect: got %d, want %d", len(parsed), SignatureSize)
 206  	}
 207  }
 208  
 209  func TestSignatureNormalization(t *testing.T) {
 210  	ctx, err := NewContext(ContextSign)
 211  	if err != nil {
 212  		t.Fatalf("Failed to create context: %v", err)
 213  	}
 214  	defer ctx.Destroy()
 215  
 216  	privKey := make([]byte, 32)
 217  	if _, err := rand.Read(privKey); err != nil {
 218  		t.Fatalf("Failed to generate random key: %v", err)
 219  	}
 220  
 221  	message := []byte("Test message")
 222  	msgHash := sha256.Sum256(message)
 223  
 224  	sig, err := ctx.Sign(msgHash[:], privKey)
 225  	if err != nil {
 226  		t.Fatalf("Failed to sign: %v", err)
 227  	}
 228  
 229  	normalized, wasNormalized, err := ctx.NormalizeSignature(sig)
 230  	if err != nil {
 231  		t.Fatalf("Failed to normalize: %v", err)
 232  	}
 233  
 234  	if len(normalized) != SignatureSize {
 235  		t.Fatalf("Normalized signature size incorrect: got %d, want %d", len(normalized), SignatureSize)
 236  	}
 237  
 238  	_ = wasNormalized // May or may not be normalized
 239  }
 240  
 241  func TestSchnorrSignAndVerify(t *testing.T) {
 242  	if schnorrsigSign32 == nil {
 243  		t.Skip("Schnorr module not available")
 244  	}
 245  
 246  	ctx, err := NewContext(ContextSign | ContextVerify)
 247  	if err != nil {
 248  		t.Fatalf("Failed to create context: %v", err)
 249  	}
 250  	defer ctx.Destroy()
 251  
 252  	privKey := make([]byte, 32)
 253  	if _, err := rand.Read(privKey); err != nil {
 254  		t.Fatalf("Failed to generate random key: %v", err)
 255  	}
 256  
 257  	keypair, err := ctx.CreateKeypair(privKey)
 258  	if err != nil {
 259  		t.Fatalf("Failed to create keypair: %v", err)
 260  	}
 261  
 262  	xonly, _, err := ctx.KeypairXOnlyPub(keypair)
 263  	if err != nil {
 264  		t.Fatalf("Failed to extract xonly pubkey: %v", err)
 265  	}
 266  
 267  	message := []byte("Test message")
 268  	msgHash := sha256.Sum256(message)
 269  
 270  	auxRand := make([]byte, 32)
 271  	if _, err := rand.Read(auxRand); err != nil {
 272  		t.Fatalf("Failed to generate aux_rand: %v", err)
 273  	}
 274  
 275  	sig, err := ctx.SchnorrSign(msgHash[:], keypair, auxRand)
 276  	if err != nil {
 277  		t.Fatalf("Failed to sign: %v", err)
 278  	}
 279  
 280  	if len(sig) != SchnorrSignatureSize {
 281  		t.Fatalf("Signature size incorrect: got %d, want %d", len(sig), SchnorrSignatureSize)
 282  	}
 283  
 284  	valid, err := ctx.SchnorrVerify(sig, msgHash[:], xonly[:])
 285  	if err != nil {
 286  		t.Fatalf("Failed to verify: %v", err)
 287  	}
 288  
 289  	if !valid {
 290  		t.Fatal("Schnorr signature should be valid")
 291  	}
 292  
 293  	// Test with wrong message
 294  	wrongMsg := []byte("Wrong message")
 295  	wrongHash := sha256.Sum256(wrongMsg)
 296  	valid2, err := ctx.SchnorrVerify(sig, wrongHash[:], xonly[:])
 297  	if err != nil {
 298  		t.Fatalf("Failed to verify wrong message: %v", err)
 299  	}
 300  
 301  	if valid2 {
 302  		t.Fatal("Schnorr signature should be invalid for wrong message")
 303  	}
 304  }
 305  
 306  func TestECDH(t *testing.T) {
 307  	if ecdh == nil {
 308  		t.Skip("ECDH module not available")
 309  	}
 310  
 311  	ctx, err := NewContext(ContextSign)
 312  	if err != nil {
 313  		t.Fatalf("Failed to create context: %v", err)
 314  	}
 315  	defer ctx.Destroy()
 316  
 317  	// Alice's keys
 318  	alicePriv := make([]byte, 32)
 319  	if _, err := rand.Read(alicePriv); err != nil {
 320  		t.Fatalf("Failed to generate Alice's key: %v", err)
 321  	}
 322  	alicePub, err := ctx.CreatePublicKey(alicePriv)
 323  	if err != nil {
 324  		t.Fatalf("Failed to create Alice's public key: %v", err)
 325  	}
 326  
 327  	// Bob's keys
 328  	bobPriv := make([]byte, 32)
 329  	if _, err := rand.Read(bobPriv); err != nil {
 330  		t.Fatalf("Failed to generate Bob's key: %v", err)
 331  	}
 332  	bobPub, err := ctx.CreatePublicKey(bobPriv)
 333  	if err != nil {
 334  		t.Fatalf("Failed to create Bob's public key: %v", err)
 335  	}
 336  
 337  	// Compute shared secrets
 338  	aliceShared, err := ctx.ECDH(bobPub, alicePriv)
 339  	if err != nil {
 340  		t.Fatalf("Failed to compute Alice's shared secret: %v", err)
 341  	}
 342  
 343  	bobShared, err := ctx.ECDH(alicePub, bobPriv)
 344  	if err != nil {
 345  		t.Fatalf("Failed to compute Bob's shared secret: %v", err)
 346  	}
 347  
 348  	if len(aliceShared) != SharedSecretSize {
 349  		t.Fatalf("Shared secret size incorrect: got %d, want %d", len(aliceShared), SharedSecretSize)
 350  	}
 351  
 352  	// Secrets should match
 353  	if string(aliceShared) != string(bobShared) {
 354  		t.Fatal("Shared secrets should match")
 355  	}
 356  }
 357  
 358  func TestRecovery(t *testing.T) {
 359  	if ecdsaSignRecoverable == nil {
 360  		t.Skip("Recovery module not available")
 361  	}
 362  
 363  	ctx, err := NewContext(ContextSign | ContextVerify)
 364  	if err != nil {
 365  		t.Fatalf("Failed to create context: %v", err)
 366  	}
 367  	defer ctx.Destroy()
 368  
 369  	privKey := make([]byte, 32)
 370  	if _, err := rand.Read(privKey); err != nil {
 371  		t.Fatalf("Failed to generate random key: %v", err)
 372  	}
 373  
 374  	originalPubKey, err := ctx.CreatePublicKey(privKey)
 375  	if err != nil {
 376  		t.Fatalf("Failed to create public key: %v", err)
 377  	}
 378  
 379  	message := []byte("Test message")
 380  	msgHash := sha256.Sum256(message)
 381  
 382  	recSig, err := ctx.SignRecoverable(msgHash[:], privKey)
 383  	if err != nil {
 384  		t.Fatalf("Failed to sign recoverable: %v", err)
 385  	}
 386  
 387  	sigBytes, recID, err := ctx.SerializeRecoverableSignatureCompact(recSig)
 388  	if err != nil {
 389  		t.Fatalf("Failed to serialize recoverable: %v", err)
 390  	}
 391  
 392  	if len(sigBytes) != 64 {
 393  		t.Fatalf("Signature size incorrect: got %d, want 64", len(sigBytes))
 394  	}
 395  
 396  	if recID < 0 || recID > 3 {
 397  		t.Fatalf("Recovery ID out of range: %d", recID)
 398  	}
 399  
 400  	parsedSig, err := ctx.ParseRecoverableSignatureCompact(sigBytes, recID)
 401  	if err != nil {
 402  		t.Fatalf("Failed to parse recoverable: %v", err)
 403  	}
 404  
 405  	recoveredPubKey, err := ctx.Recover(parsedSig, msgHash[:])
 406  	if err != nil {
 407  		t.Fatalf("Failed to recover public key: %v", err)
 408  	}
 409  
 410  	// Serialize both for comparison
 411  	origSer, err := ctx.SerializePublicKey(originalPubKey, true)
 412  	if err != nil {
 413  		t.Fatalf("Failed to serialize original: %v", err)
 414  	}
 415  
 416  	recSer, err := ctx.SerializePublicKey(recoveredPubKey, true)
 417  	if err != nil {
 418  		t.Fatalf("Failed to serialize recovered: %v", err)
 419  	}
 420  
 421  	if string(origSer) != string(recSer) {
 422  		t.Fatal("Recovered public key should match original")
 423  	}
 424  }
 425  
 426  func BenchmarkSign(b *testing.B) {
 427  	ctx, err := NewContext(ContextSign)
 428  	if err != nil {
 429  		b.Fatalf("Failed to create context: %v", err)
 430  	}
 431  	defer ctx.Destroy()
 432  
 433  	privKey := make([]byte, 32)
 434  	rand.Read(privKey)
 435  
 436  	message := []byte("Benchmark message")
 437  	msgHash := sha256.Sum256(message)
 438  
 439  	b.ResetTimer()
 440  	for i := 0; i < b.N; i++ {
 441  		_, err := ctx.Sign(msgHash[:], privKey)
 442  		if err != nil {
 443  			b.Fatalf("Failed to sign: %v", err)
 444  		}
 445  	}
 446  }
 447  
 448  func BenchmarkVerify(b *testing.B) {
 449  	ctx, err := NewContext(ContextSign | ContextVerify)
 450  	if err != nil {
 451  		b.Fatalf("Failed to create context: %v", err)
 452  	}
 453  	defer ctx.Destroy()
 454  
 455  	privKey := make([]byte, 32)
 456  	rand.Read(privKey)
 457  
 458  	pubKey, err := ctx.CreatePublicKey(privKey)
 459  	if err != nil {
 460  		b.Fatalf("Failed to create public key: %v", err)
 461  	}
 462  
 463  	message := []byte("Benchmark message")
 464  	msgHash := sha256.Sum256(message)
 465  
 466  	sig, err := ctx.Sign(msgHash[:], privKey)
 467  	if err != nil {
 468  		b.Fatalf("Failed to sign: %v", err)
 469  	}
 470  
 471  	b.ResetTimer()
 472  	for i := 0; i < b.N; i++ {
 473  		_, err := ctx.Verify(msgHash[:], sig, pubKey)
 474  		if err != nil {
 475  			b.Fatalf("Failed to verify: %v", err)
 476  		}
 477  	}
 478  }
 479