import { expect, test } from "bun:test"; import { byokAad, createSecretBox, legacyV1Encrypt, mcpAad, SERVER_KEY_AAD } from "../src/crypto"; test("round trips and uses a fresh IV each time", async () => { const box = createSecretBox("s3cret"); const a = await box.seal("sk-ant-123", "byok", byokAad("u1", "anthropic")); const b = await box.seal("sk-ant-123", "byok", byokAad("u1", "anthropic")); expect(a).not.toBe(b); expect(a).not.toContain("sk-ant-123"); expect(a.startsWith("v2.")).toBe(true); expect(await box.open(a, "byok", byokAad("u1", "anthropic"))).toBe("sk-ant-123"); expect(await box.open(b, "byok", byokAad("u1", "anthropic"))).toBe("sk-ant-123"); }); test("another secret cannot decrypt", async () => { const token = await createSecretBox("one").seal("key", "byok", "a"); await expect(createSecretBox("two").open(token, "byok", "a")).rejects.toThrow(); }); test("a tampered token is rejected", async () => { const box = createSecretBox("one"); const token = await box.seal("key", "byok", "a"); const parts = token.split("."); const ct = Buffer.from(parts[2]!, "base64"); ct[0] = ct[0]! ^ 1; await expect(box.open(`${parts[0]}.${parts[1]}.${ct.toString("base64")}`, "byok", "a")).rejects.toThrow(); await expect(box.open("garbage", "byok", "a")).rejects.toThrow(); }); test("a token opens only for its own purpose and row (domain separation and AAD)", async () => { const box = createSecretBox("one"); const byok = await box.seal("sk-user", "byok", byokAad("u1", "anthropic")); await expect(box.open(byok, "byok", byokAad("u2", "anthropic"))).rejects.toThrow(); // another user await expect(box.open(byok, "byok", byokAad("u1", "openai"))).rejects.toThrow(); // another provider await expect(box.open(byok, "server-api-key", SERVER_KEY_AAD)).rejects.toThrow(); // another purpose await expect(box.open(byok, "mcp", byokAad("u1", "anthropic"))).rejects.toThrow(); // same AAD, other HKDF key const env = await box.seal("{}", "mcp", mcpAad("fs", "env")); await expect(box.open(env, "mcp", mcpAad("fs", "headers"))).rejects.toThrow(); await expect(box.open(env, "mcp", mcpAad("web", "env"))).rejects.toThrow(); await expect(box.open(env, "byok", mcpAad("fs", "env"))).rejects.toThrow(); }); test("v1 tokens open only through openLegacy, and v2 tokens never do", async () => { const box = createSecretBox("one"); const v1 = await legacyV1Encrypt("one", "old-key"); expect(v1.startsWith("v1.")).toBe(true); expect(await box.openLegacy(v1)).toBe("old-key"); await expect(box.open(v1, "byok", byokAad("u1", "anthropic"))).rejects.toThrow(/format/); await expect(box.openLegacy(await box.seal("x", "byok", "a"))).rejects.toThrow(/format/); await expect(createSecretBox("two").openLegacy(v1)).rejects.toThrow(); });