Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,29 @@ vi.mock('node:crypto', async (importOriginal) => {
const PASSWORD = 'Ünïcödé pass 21839';
const nodeScrypt = vi.mocked(nodeCrypto.scrypt);

/**
* [#22418] Explicit budgets, sized to the measured work. Every case here
* derives scrypt keys at the production parameters (N=16384, r=16) on purpose,
* the pure-JS path at several times the native cost, so a case's wall time is
* its derivation count times what one derivation costs on the shard that runs
* it. vitest's 5000 ms default is a number nobody chose for that work.
*
* The rule: a case whose slowest `Test Core` reading is over half the default
* gets 3x that reading, rounded up to the next second. 3x clears the largest
* spread one case showed between two CI runs (1.88x) with room for a heavier
* shard. The two cases with one derivation per path (slowest reading 1435 ms)
* keep the default, which already leaves them 3.4x. When a case's derivation
* count changes, re-size it from a fresh reading, never by lowering the
* parameters.
*/
/** 3 pure-JS + 3 native derivations; CI readings 4136 and 3688 ms. */
const CROSS_VERIFY_BUDGET_MS = 13_000;
/**
* 4 pure-JS + 4 native; CI timed out at 5030 and 5039 ms, so the reading is
* projected: 4/3 of the 3 + 3 case's 4136 ms in the same run, 5515 ms.
*/
const NFKC_BUDGET_MS = 17_000;

function onWebContainer(on: boolean) {
vi.stubEnv('STACKBLITZ', on ? '1' : '');
vi.stubEnv('SHELL', on ? '/bin/jsh' : '/bin/bash');
Expand Down Expand Up @@ -67,7 +90,7 @@ describe('[#21839] share-link password: node:crypto and pure-JS scrypt are inter
expect(await verifyShareLinkPassword(PASSWORD, nativeHash)).toBe(true);
expect(await verifyShareLinkPassword('wrong 21839', nativeHash)).toBe(false);
expect(nodeScrypt).not.toHaveBeenCalled();
});
}, CROSS_VERIFY_BUDGET_MS);

it('a password whose NFKC form differs from its input is one password on both paths', async () => {
// A decomposed e + combining acute, and a fullwidth A: NFKC rewrites both.
Expand All @@ -93,7 +116,7 @@ describe('[#21839] share-link password: node:crypto and pure-JS scrypt are inter
expect(await verifyShareLinkPassword(normalised, nativeHash)).toBe(true);
expect(await verifyShareLinkPassword('cafe A 21839', nativeHash)).toBe(false);
expect(nodeScrypt).not.toHaveBeenCalled();
});
}, NFKC_BUDGET_MS);

it('the pure-JS key is byte-identical to node:crypto for the same password and salt', async () => {
onWebContainer(true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -471,6 +471,13 @@ describe('[#21839] how the password travels in', () => {
expect(loggedText(logger)).not.toContain(wrong);
});

// [#22418] An explicit budget, sized to the measured work: one mint and eight
// redemptions are nine native scrypt derivations at the production
// parameters, the most of any case in this file. Its slowest `Test Core`
// reading was 3805 ms, over half of vitest's 5000 ms default, so it gets 3x
// that, rounded up to the next second; the rule and why 3x is in
// share-link-password-webcontainer.test.ts. Every other case here read at
// most 2163 ms and keeps the default.
it('no log line carries the presented password, on any outcome', async () => {
const { http, link, logger } = await protectedConversation();
for (const pw of [PASSWORD, 'wrong one 21839']) {
Expand All @@ -481,7 +488,7 @@ describe('[#21839] how the password travels in', () => {
}
expect(loggedText(logger)).not.toContain(PASSWORD);
expect(loggedText(logger)).not.toContain('wrong one 21839');
});
}, 12_000);
});

describe('[#22049] the password header declares its encoding', () => {
Expand Down
Loading