Cover encryptDirect/decryptDirect with three scenarios (happy path, wrong recipient, tampered ciphertext) and invite link parsing with round-trip, expiry rejection, and malformed input handling. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
43 lines
1.6 KiB
TypeScript
43 lines
1.6 KiB
TypeScript
import { describe, it, expect } from "vitest";
|
|
import { encryptDirect, decryptDirect } from "../crypto/envelope";
|
|
import { generateKeypair } from "../crypto/keypair";
|
|
|
|
describe("crypto roundtrip", () => {
|
|
it("Alice encrypts for Bob, Bob decrypts successfully", async () => {
|
|
const alice = await generateKeypair();
|
|
const bob = await generateKeypair();
|
|
|
|
const plaintext = "hello world";
|
|
const envelope = await encryptDirect(plaintext, bob.publicKey, alice.secretKey);
|
|
|
|
const decrypted = await decryptDirect(envelope, alice.publicKey, bob.secretKey);
|
|
expect(decrypted).toBe(plaintext);
|
|
});
|
|
|
|
it("Carol cannot decrypt a message encrypted for Bob", async () => {
|
|
const alice = await generateKeypair();
|
|
const bob = await generateKeypair();
|
|
const carol = await generateKeypair();
|
|
|
|
const envelope = await encryptDirect("hello world", bob.publicKey, alice.secretKey);
|
|
|
|
const decrypted = await decryptDirect(envelope, alice.publicKey, carol.secretKey);
|
|
expect(decrypted).toBeNull();
|
|
});
|
|
|
|
it("tampered ciphertext returns null on decrypt", async () => {
|
|
const alice = await generateKeypair();
|
|
const bob = await generateKeypair();
|
|
|
|
const envelope = await encryptDirect("hello world", bob.publicKey, alice.secretKey);
|
|
|
|
// Flip a byte in the ciphertext
|
|
const raw = Buffer.from(envelope.ciphertext, "base64");
|
|
raw[0] = raw[0]! ^ 0xff;
|
|
const tampered = { nonce: envelope.nonce, ciphertext: raw.toString("base64") };
|
|
|
|
const decrypted = await decryptDirect(tampered, alice.publicKey, bob.secretKey);
|
|
expect(decrypted).toBeNull();
|
|
});
|
|
});
|