package seal import ( "bytes" "testing" ) func TestDeriveKey_Consistent(t *testing.T) { masterKey := []byte("test-master-key-12345") salt := "test-salt-v1" key1, err := DeriveKey(masterKey, salt) if err != nil { t.Fatalf("DeriveKey() error = %v", err) } key2, err := DeriveKey(masterKey, salt) if err != nil { t.Fatalf("DeriveKey() error = %v", err) } if key1 != key2 { t.Error("DeriveKey() should produce consistent keys for same input") } } func TestDeriveKey_DifferentSalts(t *testing.T) { masterKey := []byte("test-master-key-12345") key1, err := DeriveKey(masterKey, "salt-1") if err != nil { t.Fatalf("DeriveKey() error = %v", err) } key2, err := DeriveKey(masterKey, "salt-2") if err != nil { t.Fatalf("DeriveKey() error = %v", err) } if key1 == key2 { t.Error("DeriveKey() should produce different keys for different salts") } } func TestDeriveKey_DifferentMasterKeys(t *testing.T) { salt := "test-salt" key1, err := DeriveKey([]byte("master-key-1"), salt) if err != nil { t.Fatalf("DeriveKey() error = %v", err) } key2, err := DeriveKey([]byte("master-key-2"), salt) if err != nil { t.Fatalf("DeriveKey() error = %v", err) } if key1 == key2 { t.Error("DeriveKey() should produce different keys for different master keys") } } func TestEncryptDecrypt_RoundTrip(t *testing.T) { key, err := DeriveKey([]byte("test-key"), "test-salt") if err != nil { t.Fatalf("DeriveKey() error = %v", err) } plaintext := []byte("hello, world! this is a test message.") ciphertext, err := Encrypt(key, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := Decrypt(key, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(plaintext, decrypted) { t.Errorf("Decrypt() = %q, want %q", decrypted, plaintext) } } func TestEncryptDecrypt_EmptyPlaintext(t *testing.T) { key, _ := DeriveKey([]byte("test-key"), "test-salt") plaintext := []byte{} ciphertext, err := Encrypt(key, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } decrypted, err := Decrypt(key, ciphertext) if err != nil { t.Fatalf("Decrypt() error = %v", err) } if !bytes.Equal(plaintext, decrypted) { t.Errorf("Decrypt() = %q, want %q", decrypted, plaintext) } } func TestDecrypt_WrongKey(t *testing.T) { key1, _ := DeriveKey([]byte("key-1"), "salt") key2, _ := DeriveKey([]byte("key-2"), "salt") plaintext := []byte("secret message") ciphertext, err := Encrypt(key1, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } _, err = Decrypt(key2, ciphertext) if err == nil { t.Error("Decrypt() should fail with wrong key") } if err != ErrDecryptionFailed { t.Errorf("Decrypt() error = %v, want %v", err, ErrDecryptionFailed) } } func TestDecrypt_TamperedCiphertext(t *testing.T) { key, _ := DeriveKey([]byte("test-key"), "test-salt") plaintext := []byte("secret message") ciphertext, err := Encrypt(key, plaintext) if err != nil { t.Fatalf("Encrypt() error = %v", err) } // Tamper with the ciphertext (flip a bit in the middle) tampered := []byte(ciphertext) if len(tampered) > 10 { tampered[10] ^= 0x01 } _, err = Decrypt(key, string(tampered)) if err == nil { t.Error("Decrypt() should fail with tampered ciphertext") } } func TestDecrypt_InvalidBase64(t *testing.T) { key, _ := DeriveKey([]byte("test-key"), "test-salt") _, err := Decrypt(key, "not-valid-base64!!!") if err == nil { t.Error("Decrypt() should fail with invalid base64") } if err != ErrInvalidPayload { t.Errorf("Decrypt() error = %v, want %v", err, ErrInvalidPayload) } } func TestDecrypt_TooShort(t *testing.T) { key, _ := DeriveKey([]byte("test-key"), "test-salt") // Create a base64 string that's too short to contain nonce + auth tag _, err := Decrypt(key, "dG9vLXNob3J0") if err == nil { t.Error("Decrypt() should fail with too-short ciphertext") } if err != ErrInvalidPayload { t.Errorf("Decrypt() error = %v, want %v", err, ErrInvalidPayload) } } func TestEncrypt_ProducesDifferentCiphertexts(t *testing.T) { key, _ := DeriveKey([]byte("test-key"), "test-salt") plaintext := []byte("same message") ciphertext1, _ := Encrypt(key, plaintext) ciphertext2, _ := Encrypt(key, plaintext) if ciphertext1 == ciphertext2 { t.Error("Encrypt() should produce different ciphertexts due to random nonce") } }