54 lines
1.7 KiB
TypeScript
54 lines
1.7 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { encrypt, decrypt } from "../encrypt";
|
|
|
|
describe("encrypt / decrypt", () => {
|
|
it("round-trips a short string", () => {
|
|
const plain = "hello world";
|
|
expect(decrypt(encrypt(plain))).toBe(plain);
|
|
});
|
|
|
|
it("round-trips an empty string", () => {
|
|
expect(decrypt(encrypt(""))).toBe("");
|
|
});
|
|
|
|
it("round-trips a unicode string", () => {
|
|
const plain = "café ☕ résumé";
|
|
expect(decrypt(encrypt(plain))).toBe(plain);
|
|
});
|
|
|
|
it("round-trips a long string (API key-sized)", () => {
|
|
const plain = "sk-proj-" + "a".repeat(128);
|
|
expect(decrypt(encrypt(plain))).toBe(plain);
|
|
});
|
|
|
|
it("produces different ciphertexts for same input (random IV)", () => {
|
|
const plain = "same input";
|
|
const c1 = encrypt(plain);
|
|
const c2 = encrypt(plain);
|
|
expect(c1).not.toBe(c2);
|
|
// but both decrypt to same value
|
|
expect(decrypt(c1)).toBe(plain);
|
|
expect(decrypt(c2)).toBe(plain);
|
|
});
|
|
|
|
it("ciphertext format is iv:authTag:encrypted (3 hex segments)", () => {
|
|
const ct = encrypt("test");
|
|
const parts = ct.split(":");
|
|
expect(parts).toHaveLength(3);
|
|
parts.forEach((p) => expect(p).toMatch(/^[0-9a-f]+$/));
|
|
});
|
|
|
|
it("throws on malformed ciphertext (wrong segments)", () => {
|
|
expect(() => decrypt("notvalid")).toThrow("Invalid ciphertext format");
|
|
expect(() => decrypt("a:b")).toThrow("Invalid ciphertext format");
|
|
});
|
|
|
|
it("throws on tampered ciphertext (auth tag mismatch)", () => {
|
|
const ct = encrypt("sensitive");
|
|
const parts = ct.split(":");
|
|
// flip a byte in the encrypted payload
|
|
const tampered = parts[0] + ":" + parts[1] + ":" + "00" + parts[2]!.slice(2);
|
|
expect(() => decrypt(tampered)).toThrow();
|
|
});
|
|
});
|