fix(19): IN-02 add lockstep test pinning inlined scrypt params against canonical verifyPassword
This commit is contained in:
@@ -16,6 +16,7 @@
|
||||
*/
|
||||
|
||||
import { describe, it, expect } from 'vitest';
|
||||
import { scryptSync, randomBytes } from 'node:crypto';
|
||||
import { hashPassword, verifyPassword } from '../../src/auth/localCredentials.js';
|
||||
|
||||
describe('hashPassword / verifyPassword', () => {
|
||||
@@ -43,6 +44,42 @@ describe('hashPassword / verifyPassword', () => {
|
||||
await expect(verifyPassword('scrypt$bad$data', 'x')).resolves.toBe(false);
|
||||
});
|
||||
|
||||
it('Test 6 (IN-02): a hash produced by the INLINED scrypt parameters round-trips against the canonical verifyPassword', async () => {
|
||||
// IN-02: the PHC scrypt hash is copy-pasted in three places — the canonical module
|
||||
// (src/auth/localCredentials.ts), the break-glass CLI (scripts/reset-admin.ts), and the
|
||||
// CI seed step (.gitea/workflows/ci.yml). If the parameters ever drift, those inlined
|
||||
// copies would produce hashes the canonical verifyPassword cannot validate, silently
|
||||
// breaking login for seeded/reset accounts. This test pins the inlined parameter set:
|
||||
// if anyone changes N/r/p/KEY_LEN in the canonical module without updating the inlined
|
||||
// copies (or vice versa), this round-trip fails loudly in CI.
|
||||
//
|
||||
// These constants MUST match scripts/reset-admin.ts and .gitea/workflows/ci.yml exactly.
|
||||
const INLINE_N = 16384;
|
||||
const INLINE_R = 8;
|
||||
const INLINE_P = 1;
|
||||
const INLINE_KEY_LEN = 32;
|
||||
|
||||
const password = 'inline-roundtrip-pw';
|
||||
const salt = randomBytes(16);
|
||||
const hash = scryptSync(password, salt, INLINE_KEY_LEN, {
|
||||
N: INLINE_N,
|
||||
r: INLINE_R,
|
||||
p: INLINE_P,
|
||||
});
|
||||
const inlineEncoded = [
|
||||
'scrypt',
|
||||
INLINE_N,
|
||||
INLINE_R,
|
||||
INLINE_P,
|
||||
salt.toString('base64url'),
|
||||
hash.toString('base64url'),
|
||||
].join('$');
|
||||
|
||||
// The canonical verifyPassword must validate a hash produced by the inlined params.
|
||||
expect(await verifyPassword(inlineEncoded, password)).toBe(true);
|
||||
expect(await verifyPassword(inlineEncoded, 'wrong')).toBe(false);
|
||||
});
|
||||
|
||||
it('Test 5: encoded string has scrypt$N$r$p$salt$hash shape (6 $-delimited segments)', async () => {
|
||||
const encoded = await hashPassword('testpassword');
|
||||
const segments = encoded.split('$');
|
||||
|
||||
Reference in New Issue
Block a user