crypto.test.ts
| 1 | import { describe, expect, test } from "bun:test"; |
| 2 | import { decrypt, encrypt } from "./crypto"; |
| 3 | |
| 4 | describe("crypto (AES-256-GCM)", () => { |
| 5 | test("round-trips content with the correct password", async () => { |
| 6 | const data = new TextEncoder().encode("hello zbin 🔐 multi-byte"); |
| 7 | const enc = await encrypt(data, "correct horse battery staple"); |
| 8 | const dec = await decrypt(enc, "correct horse battery staple"); |
| 9 | expect(new TextDecoder().decode(dec)).toBe("hello zbin 🔐 multi-byte"); |
| 10 | }); |
| 11 | |
| 12 | test("wire format is salt[16] | iv[12] | ciphertext+tag", async () => { |
| 13 | const enc = await encrypt(new Uint8Array([1, 2, 3]), "pw"); |
| 14 | // 16 (salt) + 12 (iv) + 3 (plaintext) + 16 (GCM tag) |
| 15 | expect(enc.length).toBe(16 + 12 + 3 + 16); |
| 16 | }); |
| 17 | |
| 18 | test("rejects a wrong password (authenticated)", async () => { |
| 19 | const enc = await encrypt(new Uint8Array([1, 2, 3]), "right"); |
| 20 | await expect(decrypt(enc, "wrong")).rejects.toThrow(); |
| 21 | }); |
| 22 | |
| 23 | test("rejects tampered ciphertext", async () => { |
| 24 | const enc = await encrypt(new Uint8Array([9, 9, 9]), "pw"); |
| 25 | enc[enc.length - 1] ^= 0xff; // flip a tag byte |
| 26 | await expect(decrypt(enc, "pw")).rejects.toThrow(); |
| 27 | }); |
| 28 | }); |
| 29 |