20c67ef101
AES-256-CBC doesn't guarantee throwing on wrong key decryption - it depends on whether the decrypted bytes happen to have valid PKCS#7 padding. The test now verifies that decryption either throws OR returns a value different from the original plaintext. This fixes flaky test failures that started appearing after the Vitest 4.0 upgrade, where the 'Closing rpc while fetch was pending' error was a secondary symptom of the test failure causing worker teardown during module loading. Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
105 lines
3.7 KiB
TypeScript
105 lines
3.7 KiB
TypeScript
import { describe, expect, it } from "vitest";
|
|
|
|
import { symmetricDecrypt, symmetricEncrypt } from "./crypto";
|
|
|
|
describe("crypto", () => {
|
|
const testKey = "12345678901234567890123456789012"; // 32 bytes key
|
|
const testText = "Hello, World!";
|
|
|
|
describe("symmetricEncrypt", () => {
|
|
it("should encrypt text with a valid key", () => {
|
|
const encrypted = symmetricEncrypt(testText, testKey);
|
|
|
|
// Verify the format is "iv:ciphertext"
|
|
expect(encrypted).toContain(":");
|
|
const [iv, ciphertext] = encrypted.split(":");
|
|
|
|
// IV should be 32 characters (16 bytes in hex)
|
|
expect(iv).toHaveLength(32);
|
|
// Ciphertext should exist
|
|
expect(ciphertext).toBeDefined();
|
|
expect(ciphertext.length).toBeGreaterThan(0);
|
|
});
|
|
|
|
it("should produce different ciphertexts for the same input due to random IV", () => {
|
|
const encrypted1 = symmetricEncrypt(testText, testKey);
|
|
const encrypted2 = symmetricEncrypt(testText, testKey);
|
|
|
|
expect(encrypted1).not.toBe(encrypted2);
|
|
});
|
|
|
|
it("should throw error if key is not 32 bytes", () => {
|
|
const shortKey = "short";
|
|
expect(() => symmetricEncrypt(testText, shortKey)).toThrow();
|
|
});
|
|
});
|
|
|
|
describe("symmetricDecrypt", () => {
|
|
it("should correctly decrypt encrypted text", () => {
|
|
const encrypted = symmetricEncrypt(testText, testKey);
|
|
const decrypted = symmetricDecrypt(encrypted, testKey);
|
|
|
|
expect(decrypted).toBe(testText);
|
|
});
|
|
|
|
it("should throw error for malformed encrypted text", () => {
|
|
// Test with invalid IV:ciphertext format
|
|
expect(() => symmetricDecrypt("invalid", testKey)).toThrow();
|
|
expect(() => symmetricDecrypt("invalid:data", testKey)).toThrow();
|
|
expect(() => symmetricDecrypt(":", testKey)).toThrow();
|
|
});
|
|
|
|
it("should fail to decrypt correctly if wrong key is used", () => {
|
|
const encrypted = symmetricEncrypt(testText, testKey);
|
|
const wrongKey = "12345678901234567890123456789013"; // Different 32 bytes key
|
|
|
|
// AES-256-CBC doesn't guarantee throwing on wrong key - it depends on whether
|
|
// the decrypted bytes happen to have valid PKCS#7 padding. The test verifies
|
|
// that decryption either throws OR returns a value different from the original.
|
|
let decryptedWithWrongKey: string | null = null;
|
|
let threwError = false;
|
|
|
|
try {
|
|
decryptedWithWrongKey = symmetricDecrypt(encrypted, wrongKey);
|
|
} catch {
|
|
threwError = true;
|
|
}
|
|
|
|
// Either it threw an error, or the decrypted value is not the original text
|
|
expect(threwError || decryptedWithWrongKey !== testText).toBe(true);
|
|
});
|
|
|
|
it("should handle empty string encryption/decryption", () => {
|
|
const emptyText = "";
|
|
const encrypted = symmetricEncrypt(emptyText, testKey);
|
|
const decrypted = symmetricDecrypt(encrypted, testKey);
|
|
|
|
expect(decrypted).toBe(emptyText);
|
|
});
|
|
|
|
it("should handle long text encryption/decryption", () => {
|
|
const longText = "a".repeat(1000);
|
|
const encrypted = symmetricEncrypt(longText, testKey);
|
|
const decrypted = symmetricDecrypt(encrypted, testKey);
|
|
|
|
expect(decrypted).toBe(longText);
|
|
});
|
|
|
|
it("should handle special characters", () => {
|
|
const specialChars = "!@#$%^&*()_+-=[]{}|;:'\",.<>?/\\`~";
|
|
const encrypted = symmetricEncrypt(specialChars, testKey);
|
|
const decrypted = symmetricDecrypt(encrypted, testKey);
|
|
|
|
expect(decrypted).toBe(specialChars);
|
|
});
|
|
|
|
it("should handle unicode characters", () => {
|
|
const unicodeText = "Hello, 世界! 👋 🌍";
|
|
const encrypted = symmetricEncrypt(unicodeText, testKey);
|
|
const decrypted = symmetricDecrypt(encrypted, testKey);
|
|
|
|
expect(decrypted).toBe(unicodeText);
|
|
});
|
|
});
|
|
});
|