Files
STTracker/packages/core/test/crypto.test.ts
T

40 lines
1.6 KiB
TypeScript

import { describe, expect, test } from "bun:test";
import { decryptJson, encryptJson } from "../src/crypto.ts";
import { CryptoError } from "../src/errors.ts";
describe("crypto", () => {
test("round-trips JSON", async () => {
const value = { token: "abc", n: [1, 2, { x: null }] };
const blob = await encryptJson("s3cret", value);
expect(blob).toMatch(/^v1\.[A-Za-z0-9+/=]+\.[A-Za-z0-9+/=]+$/);
expect(await decryptJson("s3cret", blob)).toEqual(value);
});
test("uses a fresh IV each time", async () => {
expect(await encryptJson("k", 1)).not.toBe(await encryptJson("k", 1));
});
test("wrong secret throws CryptoError", async () => {
const blob = await encryptJson("right", { a: 1 });
await expect(decryptJson("wrong", blob)).rejects.toBeInstanceOf(CryptoError);
});
test("malformed blob throws CryptoError", async () => {
await expect(decryptJson("k", "garbage")).rejects.toBeInstanceOf(CryptoError);
await expect(decryptJson("k", "v2.AA==.AA==")).rejects.toBeInstanceOf(CryptoError);
});
test("IV decodes to 12 bytes", async () => {
const blob = await encryptJson("k", { a: 1 });
expect(Buffer.from(blob.split(".")[1]!, "base64")).toHaveLength(12);
});
test("flipping a ciphertext byte throws CryptoError", async () => {
const [v, iv, ct] = (await encryptJson("k", { a: 1 })).split(".");
const bytes = Buffer.from(ct!, "base64");
bytes[0] = bytes[0]! ^ 0xff;
const tampered = `${v}.${iv}.${bytes.toString("base64")}`;
await expect(decryptJson("k", tampered)).rejects.toBeInstanceOf(CryptoError);
});
});