import { describe, it, expect } from 'vitest'; import { credKeyFromEnv, sealSecret, openSecret, SECRET_KEY_VERSION } from './secret-crypto'; const KEY = Buffer.alloc(32, 7); // deterministic 32-byte key for tests describe('secret-crypto', () => { it('round-trips a secret through seal → open', () => { const sealed = sealSecret('sk_live_abc123', KEY); expect(sealed.keyVersion).toBe(SECRET_KEY_VERSION); expect(sealed.cipherText).not.toContain('sk_live_abc123'); expect(openSecret(sealed, KEY)).toBe('sk_live_abc123'); }); it('produces a distinct ciphertext each time (random IV)', () => { const a = sealSecret('same', KEY); const b = sealSecret('same', KEY); expect(a.cipherText).not.toBe(b.cipherText); expect(a.iv).not.toBe(b.iv); }); it('fails to open with the wrong key', () => { const sealed = sealSecret('top-secret', KEY); expect(() => openSecret(sealed, Buffer.alloc(32, 9))).toThrow(); }); it('fails to open if the ciphertext is tampered (GCM auth)', () => { const sealed = sealSecret('top-secret', KEY); const bad = { ...sealed, cipherText: Buffer.from('deadbeef', 'hex').toString('base64') }; expect(() => openSecret(bad, KEY)).toThrow(); }); it('credKeyFromEnv returns null when unset and rejects a wrong-length key', () => { expect(credKeyFromEnv({})).toBeNull(); expect(() => credKeyFromEnv({ IIOS_CRED_KEY: Buffer.alloc(16).toString('base64') })).toThrow(/32 bytes/); const key = credKeyFromEnv({ IIOS_CRED_KEY: KEY.toString('base64') }); expect(key?.length).toBe(32); }); });