profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
crypto.test.ts 2,001 bytes
1 import { describe, expect, it } from 'vitest';
2 import { decryptSecret, encryptSecret, maskKey, safeEqual } from './crypto';
3
4 describe('encryptSecret / decryptSecret', () => {
5 it('round-trips a secret', () => {
6 const secret = 'sk-or-v1-abcdef0123456789';
7 const encrypted = encryptSecret(secret);
8 expect(decryptSecret(encrypted)).toBe(secret);
9 });
10
11 it('produces a versioned, dot-delimited ciphertext that hides the plaintext', () => {
12 const encrypted = encryptSecret('super-secret-key');
13 expect(encrypted.startsWith('v1.')).toBe(true);
14 expect(encrypted.split('.')).toHaveLength(4);
15 expect(encrypted).not.toContain('super-secret-key');
16 });
17
18 it('uses a fresh IV so identical plaintext encrypts differently', () => {
19 const a = encryptSecret('same');
20 const b = encryptSecret('same');
21 expect(a).not.toBe(b);
22 expect(decryptSecret(a)).toBe('same');
23 expect(decryptSecret(b)).toBe('same');
24 });
25
26 it('rejects tampered ciphertext (GCM auth tag)', () => {
27 const encrypted = encryptSecret('integrity-matters');
28 const parts = encrypted.split('.');
29 // Flip a character in the ciphertext segment.
30 const tampered = [parts[0], parts[1], parts[2], `${parts[3]!.slice(0, -1)}X`].join('.');
31 expect(() => decryptSecret(tampered)).toThrow();
32 });
33
34 it('rejects a malformed payload', () => {
35 expect(() => decryptSecret('not-a-valid-payload')).toThrow();
36 expect(() => decryptSecret('v2.a.b.c')).toThrow();
37 });
38 });
39
40 describe('maskKey', () => {
41 it('shows a prefix and suffix only', () => {
42 expect(maskKey('sk-or-v1-abcdef0123456789xyz')).toBe('sk-or-...9xyz');
43 });
44 it('fully masks short values', () => {
45 expect(maskKey('short')).toBe('••••');
46 });
47 });
48
49 describe('safeEqual', () => {
50 it('is true for equal strings and false otherwise', () => {
51 expect(safeEqual('token', 'token')).toBe(true);
52 expect(safeEqual('token', 'tokes')).toBe(false);
53 expect(safeEqual('token', 'tokenn')).toBe(false);
54 });
55 });
56