205a5a36c6
- 8 crypto tests: key derivation, encrypt/decrypt round-trip, wrong key, nonce uniqueness - 6 auth tests: password hash/verify, JWT generate/validate, token revocation - 14 store tests: project CRUD, user CRUD, stage/deploy lifecycle, pagination, cascade deletes - Fix stages CREATE TABLE schema to include notification_url column - Total: 28 tests, all passing
137 lines
3.4 KiB
Go
137 lines
3.4 KiB
Go
package crypto
|
|
|
|
import (
|
|
"testing"
|
|
)
|
|
|
|
func TestDeriveKey(t *testing.T) {
|
|
key := DeriveKey("test-passphrase-that-is-long-enough")
|
|
if key == [32]byte{} {
|
|
t.Fatal("DeriveKey returned zero key")
|
|
}
|
|
// Same input produces same output
|
|
key2 := DeriveKey("test-passphrase-that-is-long-enough")
|
|
if key != key2 {
|
|
t.Fatal("DeriveKey is not deterministic")
|
|
}
|
|
// Different input produces different output
|
|
key3 := DeriveKey("different-passphrase-also-long-enough")
|
|
if key == key3 {
|
|
t.Fatal("DeriveKey produced same key for different inputs")
|
|
}
|
|
}
|
|
|
|
func TestEncryptDecryptRoundTrip(t *testing.T) {
|
|
key := DeriveKey("test-key-for-encryption-testing-1234")
|
|
plaintext := "super-secret-value"
|
|
|
|
encrypted, err := Encrypt(key, plaintext)
|
|
if err != nil {
|
|
t.Fatalf("Encrypt failed: %v", err)
|
|
}
|
|
if encrypted == plaintext {
|
|
t.Fatal("Encrypt returned plaintext")
|
|
}
|
|
if encrypted == "" {
|
|
t.Fatal("Encrypt returned empty string")
|
|
}
|
|
|
|
decrypted, err := Decrypt(key, encrypted)
|
|
if err != nil {
|
|
t.Fatalf("Decrypt failed: %v", err)
|
|
}
|
|
if decrypted != plaintext {
|
|
t.Fatalf("Decrypt mismatch: got %q, want %q", decrypted, plaintext)
|
|
}
|
|
}
|
|
|
|
func TestDecryptWithWrongKey(t *testing.T) {
|
|
key1 := DeriveKey("key-one-for-testing-encryption-1234")
|
|
key2 := DeriveKey("key-two-for-testing-encryption-5678")
|
|
|
|
encrypted, err := Encrypt(key1, "secret")
|
|
if err != nil {
|
|
t.Fatalf("Encrypt failed: %v", err)
|
|
}
|
|
|
|
_, err = Decrypt(key2, encrypted)
|
|
if err == nil {
|
|
t.Fatal("Decrypt with wrong key should have failed")
|
|
}
|
|
}
|
|
|
|
func TestEncryptIfNotEmpty(t *testing.T) {
|
|
key := DeriveKey("test-key-for-encryption-testing-1234")
|
|
|
|
result, err := EncryptIfNotEmpty(key, "")
|
|
if err != nil {
|
|
t.Fatalf("EncryptIfNotEmpty with empty input failed: %v", err)
|
|
}
|
|
if result != "" {
|
|
t.Fatal("EncryptIfNotEmpty should return empty for empty input")
|
|
}
|
|
|
|
result, err = EncryptIfNotEmpty(key, "value")
|
|
if err != nil {
|
|
t.Fatalf("EncryptIfNotEmpty failed: %v", err)
|
|
}
|
|
if result == "" || result == "value" {
|
|
t.Fatal("EncryptIfNotEmpty should encrypt non-empty input")
|
|
}
|
|
}
|
|
|
|
func TestKeyFromEnv(t *testing.T) {
|
|
// Test with no key set
|
|
t.Setenv("ENCRYPTION_KEY", "")
|
|
_, err := KeyFromEnv()
|
|
if err == nil {
|
|
t.Fatal("KeyFromEnv should fail with empty ENCRYPTION_KEY")
|
|
}
|
|
|
|
// Test with valid key
|
|
t.Setenv("ENCRYPTION_KEY", "a-very-long-encryption-key-that-is-definitely-over-32-chars")
|
|
key, err := KeyFromEnv()
|
|
if err != nil {
|
|
t.Fatalf("KeyFromEnv failed with valid key: %v", err)
|
|
}
|
|
if key == [32]byte{} {
|
|
t.Fatal("KeyFromEnv returned zero key")
|
|
}
|
|
}
|
|
|
|
func TestEncryptProducesDifferentCiphertexts(t *testing.T) {
|
|
key := DeriveKey("test-key-for-nonce-uniqueness-1234")
|
|
|
|
enc1, err := Encrypt(key, "same-plaintext")
|
|
if err != nil {
|
|
t.Fatalf("Encrypt 1 failed: %v", err)
|
|
}
|
|
|
|
enc2, err := Encrypt(key, "same-plaintext")
|
|
if err != nil {
|
|
t.Fatalf("Encrypt 2 failed: %v", err)
|
|
}
|
|
|
|
if enc1 == enc2 {
|
|
t.Fatal("Two encryptions of the same plaintext should produce different ciphertexts (random nonce)")
|
|
}
|
|
}
|
|
|
|
func TestDecryptInvalidHex(t *testing.T) {
|
|
key := DeriveKey("test-key-for-invalid-hex-testing")
|
|
|
|
_, err := Decrypt(key, "not-valid-hex!!!")
|
|
if err == nil {
|
|
t.Fatal("Decrypt should fail with invalid hex input")
|
|
}
|
|
}
|
|
|
|
func TestDecryptTooShort(t *testing.T) {
|
|
key := DeriveKey("test-key-for-short-ciphertext-test")
|
|
|
|
_, err := Decrypt(key, "aabb")
|
|
if err == nil {
|
|
t.Fatal("Decrypt should fail with ciphertext shorter than nonce")
|
|
}
|
|
}
|