File size: 1,824 Bytes
92a1d83
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
import { describe, expect, it, beforeAll } from "bun:test";
import { encryptApiKey, decryptApiKey } from "../encryption";

const TEST_KEY = "test-encryption-key-1234567890abcd"; // 32+ chars
const TEST_PLAINTEXT = "sk-my-secret-api-key-abc123";

beforeAll(() => {
  process.env.API_KEY_ENCRYPTION_KEY = TEST_KEY;
});

describe("encryptApiKey / decryptApiKey", () => {
  it("round-trips a plaintext successfully", () => {
    const encrypted = encryptApiKey(TEST_PLAINTEXT);
    expect(encrypted).toBeTruthy();
    expect(typeof encrypted).toBe("string");

    const decrypted = decryptApiKey(encrypted);
    expect(decrypted).toBe(TEST_PLAINTEXT);
  });

  it("produces different ciphertext each call (uses random salt/iv)", () => {
    const result1 = encryptApiKey(TEST_PLAINTEXT);
    const result2 = encryptApiKey(TEST_PLAINTEXT);
    expect(result1).not.toBe(result2);
  });

  it("handles empty string", () => {
    const encrypted = encryptApiKey("");
    const decrypted = decryptApiKey(encrypted);
    expect(decrypted).toBe("");
  });

  it("handles special characters", () => {
    const special = "abc123!@#$%^&*()_+-=[]{}|;':\",./<>?`~你好日本語";
    const encrypted = encryptApiKey(special);
    const decrypted = decryptApiKey(encrypted);
    expect(decrypted).toBe(special);
  });
});

describe("decryptApiKey — error handling", () => {
  it("throws on invalid format (not 4 parts)", () => {
    expect(() => decryptApiKey("invalid-format")).toThrow("Invalid encrypted API key format");
  });

  it("throws on tampered ciphertext", () => {
    const encrypted = encryptApiKey(TEST_PLAINTEXT);
    const parts = encrypted.split(":");
    // Tamper the ciphertext part
    parts[3] = "tampered-data";
    const tampered = parts.join(":");
    expect(() => decryptApiKey(tampered)).toThrow();
  });
});