fix(db): generate unique random salt per encryptSecret call (GRO-453)

Use a 16-byte random salt per encryption instead of the fixed
"groombook-auth-provider-config" salt. This prevents identical
plaintexts from producing identical ciphertexts, closing the
timing/anagram security gap identified in GRO-452.

New format: salt:iv:ciphertext:authTag (all base64).
Legacy format (iv:ciphertext:authTag) is still accepted for
backward-compatible decryption of existing stored values.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
Paperclip
2026-04-04 21:25:32 +00:00
parent a2cb3bfc21
commit 78a6758349
2 changed files with 13 additions and 17 deletions
+5 -3
View File
@@ -61,8 +61,10 @@ describe("encryptSecret / decryptSecret", () => {
});
it("throws when decrypting invalid format (wrong number of parts)", () => {
// 2 parts is invalid for both legacy (3) and new (4) format
const invalid = "not-enough-parts";
const encrypted = encryptSecret("test");
// Replace the last two parts with a single part to create a 2-part string
// This can't be parsed as either legacy (3 parts) or new (4 parts) format
const invalid = encrypted.replace(/:[^:]+$/, "").replace(/:[^:]+$/, "");
expect(() => decryptSecret(invalid)).toThrow(
"Invalid encrypted value format: expected salt:iv:ciphertext:authTag or iv:ciphertext:authTag"
@@ -92,4 +94,4 @@ describe("encryptSecret / decryptSecret", () => {
expect(decrypted).toBe(plaintext);
});
});
});