package engine import ( "bytes" "crypto/ecdh" "crypto/rand" "encoding/hex" "strings" "testing" ) func TestNewEngine(t *testing.T) { e := NewEngine() if e == nil { t.Fatal("NewEngine() returned nil") } } func TestGenerateKeyPair(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } if kp.PrivateKey == nil { t.Error("PrivateKey is nil") } if kp.PublicKey == nil { t.Error("PublicKey is nil") } // Verify key lengths (X25519 keys are 32 bytes) if len(kp.PrivateKey.Bytes()) != 32 { t.Errorf("PrivateKey length = %d, want 32", len(kp.PrivateKey.Bytes())) } if len(kp.PublicKey.Bytes()) != 32 { t.Errorf("PublicKey length = %d, want 32", len(kp.PublicKey.Bytes())) } } func TestGenerateKeyPair_Uniqueness(t *testing.T) { e := NewEngine() kp1, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } kp2, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } if bytes.Equal(kp1.PrivateKey.Bytes(), kp2.PrivateKey.Bytes()) { t.Error("Two generated key pairs have identical private keys") } if bytes.Equal(kp1.PublicKey.Bytes(), kp2.PublicKey.Bytes()) { t.Error("Two generated key pairs have identical public keys") } } func TestEncodePublicKey(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } encoded := kp.EncodePublicKey() // Should be 64 hex characters (32 bytes * 2) if len(encoded) != 64 { t.Errorf("EncodePublicKey() length = %d, want 64", len(encoded)) } // Should be valid hex _, err = hex.DecodeString(encoded) if err != nil { t.Errorf("EncodePublicKey() produced invalid hex: %v", err) } } func TestEncodePrivateKey(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } encoded := kp.EncodePrivateKey() // Should be 64 hex characters (32 bytes * 2) if len(encoded) != 64 { t.Errorf("EncodePrivateKey() length = %d, want 64", len(encoded)) } // Should be valid hex _, err = hex.DecodeString(encoded) if err != nil { t.Errorf("EncodePrivateKey() produced invalid hex: %v", err) } } func TestDecodePrivateKey(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } encoded := kp.EncodePrivateKey() decoded, err := e.DecodePrivateKey(encoded) if err != nil { t.Fatalf("DecodePrivateKey() error = %v", err) } if !bytes.Equal(decoded.Bytes(), kp.PrivateKey.Bytes()) { t.Error("Decoded private key does not match original") } } func TestDecodePublicKey(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } encoded := kp.EncodePublicKey() decoded, err := e.DecodePublicKey(encoded) if err != nil { t.Fatalf("DecodePublicKey() error = %v", err) } if !bytes.Equal(decoded.Bytes(), kp.PublicKey.Bytes()) { t.Error("Decoded public key does not match original") } } func TestDecodePrivateKey_InvalidHex(t *testing.T) { e := NewEngine() _, err := e.DecodePrivateKey("not-valid-hex!") if err == nil { t.Error("DecodePrivateKey() should error on invalid hex") } } func TestDecodePublicKey_InvalidHex(t *testing.T) { e := NewEngine() _, err := e.DecodePublicKey("not-valid-hex!") if err == nil { t.Error("DecodePublicKey() should error on invalid hex") } } func TestDecodePrivateKey_WrongLength(t *testing.T) { e := NewEngine() // 16 bytes instead of 32 shortKey := strings.Repeat("00", 16) _, err := e.DecodePrivateKey(shortKey) if err == nil { t.Error("DecodePrivateKey() should error on wrong length key") } } func TestDecodePublicKey_WrongLength(t *testing.T) { e := NewEngine() // 16 bytes instead of 32 shortKey := strings.Repeat("00", 16) _, err := e.DecodePublicKey(shortKey) if err == nil { t.Error("DecodePublicKey() should error on wrong length key") } } func TestEncryptDecrypt_RoundTrip(t *testing.T) { e := NewEngine() // Generate sender and recipient key pairs sender, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for sender error = %v", err) } recipient, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for recipient error = %v", err) } plaintext := []byte("Hello, World! This is a secret message.") // Encrypt ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Decrypt decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("Decrypted message = %q, want %q", decrypted, plaintext) } } func TestEncryptDecrypt_EmptyMessage(t *testing.T) { e := NewEngine() sender, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for sender error = %v", err) } recipient, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for recipient error = %v", err) } plaintext := []byte("") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("Decrypted message = %q, want empty string", decrypted) } } func TestEncryptDecrypt_LargeMessage(t *testing.T) { e := NewEngine() sender, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for sender error = %v", err) } recipient, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for recipient error = %v", err) } // Create a 1MB message plaintext := make([]byte, 1024*1024) if _, err := rand.Read(plaintext); err != nil { t.Fatalf("Failed to generate random plaintext: %v", err) } ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Error("Decrypted large message does not match original") } } func TestEncryptDecrypt_BinaryData(t *testing.T) { e := NewEngine() sender, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for sender error = %v", err) } recipient, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() for recipient error = %v", err) } // Binary data with null bytes and special characters plaintext := []byte{0x00, 0x01, 0x02, 0xff, 0xfe, 0x00, 0x00, 0x10, 0x20} ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("Decrypted binary data = %v, want %v", decrypted, plaintext) } } func TestDecrypt_WrongRecipientKey(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() wrongRecipient, _ := e.GenerateKeyPair() plaintext := []byte("Secret message") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Try to decrypt with wrong recipient's private key _, err = e.Decrypt(wrongRecipient.PrivateKey, sender.PublicKey, ciphertext) if err == nil { t.Error("Decrypt() should fail with wrong recipient key") } } func TestDecrypt_WrongSenderPublicKey(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() wrongSender, _ := e.GenerateKeyPair() plaintext := []byte("Secret message") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Try to decrypt with wrong sender's public key _, err = e.Decrypt(recipient.PrivateKey, wrongSender.PublicKey, ciphertext) if err == nil { t.Error("Decrypt() should fail with wrong sender public key") } } func TestDecrypt_TamperedCiphertext(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Secret message") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Tamper with the ciphertext (flip a bit in the actual ciphertext portion) if len(ciphertext) > 60 { ciphertext[60] ^= 0x01 } _, err = e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err == nil { t.Error("Decrypt() should fail with tampered ciphertext") } } func TestDecrypt_TruncatedMessage(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Secret message") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Truncate the message truncated := ciphertext[:len(ciphertext)-10] _, err = e.Decrypt(recipient.PrivateKey, sender.PublicKey, truncated) if err == nil { t.Error("Decrypt() should fail with truncated ciphertext") } } func TestDecrypt_MessageTooShort(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() // Message shorter than pubKeySize + nonceSize (32 + 24 = 56 bytes) shortMessage := make([]byte, 50) _, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, shortMessage) if err == nil { t.Error("Decrypt() should fail with message too short") } if err.Error() != "message too short" { t.Errorf("Decrypt() error = %v, want 'message too short'", err) } } func TestDecrypt_InvalidEphemeralPublicKey(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() // Create a message with invalid ephemeral public key (all zeros) invalidMessage := make([]byte, 100) _, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, invalidMessage) // This should fail during decryption due to authentication failure if err == nil { t.Error("Decrypt() should fail with invalid ephemeral public key") } } func TestEncrypt_DifferentCiphertextEachTime(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Same message") ciphertext1, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("First Encrypt() error = %v", err) } ciphertext2, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Second Encrypt() error = %v", err) } // Due to ephemeral keys and random nonce, ciphertexts should be different if bytes.Equal(ciphertext1, ciphertext2) { t.Error("Encrypting same message twice should produce different ciphertexts (due to ephemeral keys)") } // But both should decrypt to the same plaintext decrypted1, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext1) if err != nil { t.Fatalf("Decrypt first error = %v", err) } decrypted2, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext2) if err != nil { t.Fatalf("Decrypt second error = %v", err) } if !bytes.Equal(decrypted1, plaintext) || !bytes.Equal(decrypted2, plaintext) { t.Error("Both ciphertexts should decrypt to the same plaintext") } } func TestCiphertextFormat(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Test message") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Ciphertext format: [EphemeralPub (32)] [Nonce (24)] [Ciphertext + Tag (len(plaintext) + 16)] expectedMinLength := 32 + 24 + len(plaintext) + 16 // 16 is Poly1305 tag size if len(ciphertext) != expectedMinLength { t.Errorf("Ciphertext length = %d, want %d", len(ciphertext), expectedMinLength) } } func TestKeyPairConsistency(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } // Public key should be derivable from private key derivedPub := kp.PrivateKey.PublicKey() if !bytes.Equal(derivedPub.Bytes(), kp.PublicKey.Bytes()) { t.Error("Public key should be consistent with private key") } } func TestEncodeDecodeRoundTrip(t *testing.T) { e := NewEngine() kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } // Test private key round trip privEncoded := kp.EncodePrivateKey() privDecoded, err := e.DecodePrivateKey(privEncoded) if err != nil { t.Fatalf("DecodePrivateKey() error = %v", err) } // Test public key round trip pubEncoded := kp.EncodePublicKey() pubDecoded, err := e.DecodePublicKey(pubEncoded) if err != nil { t.Fatalf("DecodePublicKey() error = %v", err) } // Use decoded keys for encryption/decryption recipient, _ := e.GenerateKeyPair() plaintext := []byte("Round trip test") ciphertext, err := e.Encrypt(privDecoded, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt with decoded key error = %v", err) } decrypted, err := e.Decrypt(recipient.PrivateKey, pubDecoded, ciphertext) if err != nil { t.Fatalf("Decrypt with decoded key error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Error("Decoded keys should work correctly for encryption/decryption") } } func TestMultipleRecipients(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient1, _ := e.GenerateKeyPair() recipient2, _ := e.GenerateKeyPair() plaintext := []byte("Message for multiple recipients") // Encrypt for recipient1 ciphertext1, err := e.Encrypt(sender.PrivateKey, recipient1.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt for recipient1 error = %v", err) } // Encrypt for recipient2 ciphertext2, err := e.Encrypt(sender.PrivateKey, recipient2.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt for recipient2 error = %v", err) } // Both should be able to decrypt their own messages decrypted1, err := e.Decrypt(recipient1.PrivateKey, sender.PublicKey, ciphertext1) if err != nil { t.Fatalf("Decrypt for recipient1 error = %v", err) } if !bytes.Equal(decrypted1, plaintext) { t.Error("Recipient1 should be able to decrypt their message") } decrypted2, err := e.Decrypt(recipient2.PrivateKey, sender.PublicKey, ciphertext2) if err != nil { t.Fatalf("Decrypt for recipient2 error = %v", err) } if !bytes.Equal(decrypted2, plaintext) { t.Error("Recipient2 should be able to decrypt their message") } // Cross decryption should fail _, err = e.Decrypt(recipient1.PrivateKey, sender.PublicKey, ciphertext2) if err == nil { t.Error("Recipient1 should NOT be able to decrypt recipient2's message") } _, err = e.Decrypt(recipient2.PrivateKey, sender.PublicKey, ciphertext1) if err == nil { t.Error("Recipient2 should NOT be able to decrypt recipient1's message") } } func TestUnicodeMessage(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() // Unicode message with various scripts plaintext := []byte("Hello 世界! Привет мир! 🔐🔑") ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("Decrypted unicode message = %q, want %q", decrypted, plaintext) } } // Benchmark tests func BenchmarkGenerateKeyPair(b *testing.B) { e := NewEngine() b.ResetTimer() for i := 0; i < b.N; i++ { _, err := e.GenerateKeyPair() if err != nil { b.Fatal(err) } } } func BenchmarkEncrypt(b *testing.B) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Benchmark encryption test message") b.ResetTimer() for i := 0; i < b.N; i++ { _, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { b.Fatal(err) } } } func BenchmarkDecrypt(b *testing.B) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Benchmark decryption test message") ciphertext, _ := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) b.ResetTimer() for i := 0; i < b.N; i++ { _, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { b.Fatal(err) } } } func BenchmarkEncryptLargeMessage(b *testing.B) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := make([]byte, 1024*1024) // 1MB rand.Read(plaintext) b.ResetTimer() for i := 0; i < b.N; i++ { _, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { b.Fatal(err) } } } // Test that verifies the authentication property - message must come from correct sender func TestSenderAuthentication(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() imposter, _ := e.GenerateKeyPair() plaintext := []byte("Authenticated message") // Sender encrypts ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Recipient tries to decrypt thinking it's from imposter - should fail _, err = e.Decrypt(recipient.PrivateKey, imposter.PublicKey, ciphertext) if err == nil { t.Error("Decryption should fail when wrong sender public key is provided") } // Recipient decrypts with correct sender public key - should succeed decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() with correct sender should succeed: %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Error("Decrypted message should match plaintext") } } // Test forward secrecy by verifying ephemeral keys are different each encryption func TestForwardSecrecy(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() plaintext := []byte("Forward secrecy test") ciphertext1, _ := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) ciphertext2, _ := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) // Extract ephemeral public keys (first 32 bytes) ephemeralPub1 := ciphertext1[:32] ephemeralPub2 := ciphertext2[:32] // Ephemeral keys should be different for each encryption if bytes.Equal(ephemeralPub1, ephemeralPub2) { t.Error("Ephemeral public keys should be different for each encryption (forward secrecy)") } } // Test with known test vectors (useful for cross-implementation testing) func TestDecodeKnownKeys(t *testing.T) { e := NewEngine() // Generate a key pair and verify it can be encoded and decoded kp, err := e.GenerateKeyPair() if err != nil { t.Fatalf("GenerateKeyPair() error = %v", err) } privHex := kp.EncodePrivateKey() pubHex := kp.EncodePublicKey() // Verify the hex strings are lowercase if privHex != strings.ToLower(privHex) { t.Error("Private key hex should be lowercase") } if pubHex != strings.ToLower(pubHex) { t.Error("Public key hex should be lowercase") } // Verify decoding priv, err := e.DecodePrivateKey(privHex) if err != nil { t.Fatalf("DecodePrivateKey() error = %v", err) } pub, err := e.DecodePublicKey(pubHex) if err != nil { t.Fatalf("DecodePublicKey() error = %v", err) } // Verify the decoded public key matches derived public key if !bytes.Equal(priv.PublicKey().Bytes(), pub.Bytes()) { t.Error("Decoded public key should match public key derived from decoded private key") } } // Test edge case: decode with uppercase hex (should work since hex.DecodeString handles both) func TestDecodeUppercaseHex(t *testing.T) { e := NewEngine() kp, _ := e.GenerateKeyPair() privHex := strings.ToUpper(kp.EncodePrivateKey()) pubHex := strings.ToUpper(kp.EncodePublicKey()) priv, err := e.DecodePrivateKey(privHex) if err != nil { t.Fatalf("DecodePrivateKey() should handle uppercase hex: %v", err) } pub, err := e.DecodePublicKey(pubHex) if err != nil { t.Fatalf("DecodePublicKey() should handle uppercase hex: %v", err) } if !bytes.Equal(priv.Bytes(), kp.PrivateKey.Bytes()) { t.Error("Decoded private key should match original") } if !bytes.Equal(pub.Bytes(), kp.PublicKey.Bytes()) { t.Error("Decoded public key should match original") } } // Fuzz-like test with random message sizes func TestRandomMessageSizes(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() sizes := []int{0, 1, 15, 16, 17, 31, 32, 33, 63, 64, 65, 127, 128, 256, 512, 1000, 4096} for _, size := range sizes { t.Run(string(rune(size)), func(t *testing.T) { plaintext := make([]byte, size) if size > 0 { rand.Read(plaintext) } ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() with size %d error = %v", size, err) } decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() with size %d error = %v", size, err) } if !bytes.Equal(decrypted, plaintext) { t.Errorf("Round trip failed for size %d", size) } }) } } // Test concurrent encryption/decryption func TestConcurrentOperations(t *testing.T) { e := NewEngine() sender, _ := e.GenerateKeyPair() recipient, _ := e.GenerateKeyPair() const numGoroutines = 100 done := make(chan bool, numGoroutines) for i := 0; i < numGoroutines; i++ { go func(id int) { plaintext := []byte("Concurrent message " + string(rune('A'+id%26))) ciphertext, err := e.Encrypt(sender.PrivateKey, recipient.PublicKey, plaintext) if err != nil { t.Errorf("Goroutine %d: Encrypt() error = %v", id, err) done <- false return } decrypted, err := e.Decrypt(recipient.PrivateKey, sender.PublicKey, ciphertext) if err != nil { t.Errorf("Goroutine %d: Decrypt() error = %v", id, err) done <- false return } if !bytes.Equal(decrypted, plaintext) { t.Errorf("Goroutine %d: decrypted != plaintext", id) done <- false return } done <- true }(i) } for i := 0; i < numGoroutines; i++ { <-done } } // Test self-encryption (sender encrypts to themselves) func TestSelfEncryption(t *testing.T) { e := NewEngine() user, _ := e.GenerateKeyPair() plaintext := []byte("Message to myself") ciphertext, err := e.Encrypt(user.PrivateKey, user.PublicKey, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := e.Decrypt(user.PrivateKey, user.PublicKey, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(decrypted, plaintext) { t.Error("Self-encryption should work correctly") } } // Ensure interface compatibility (Engine implements expected methods) func TestEngineInterface(t *testing.T) { e := NewEngine() // Test that all public methods exist and have correct signatures var _ func() (*KeyPair, error) = e.GenerateKeyPair var _ func(string) (*ecdh.PrivateKey, error) = e.DecodePrivateKey var _ func(string) (*ecdh.PublicKey, error) = e.DecodePublicKey var _ func(*ecdh.PrivateKey, *ecdh.PublicKey, []byte) ([]byte, error) = e.Encrypt var _ func(*ecdh.PrivateKey, *ecdh.PublicKey, []byte) ([]byte, error) = e.Decrypt }