release: v0.19.0
Release v0.19.0. See the `## [0.19.0] — 2026-09-29` section of [CHANGELOG.md](https://github.com/ralksta/immich-folio/blob/dev/CHANGELOG.md) for the full list. Highlights: client proofing links (#683), custom content pages (#738), asset picker search (#740), concurrent-edit detection (#742), env-locked settings (#739), an accessibility baseline (#741), three security fixes with advisories (#737, #755, #759), and a pre-release quality pass (#780–#797). --------- Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: ralksta <ralksta@users.noreply.github.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: Ralf <rohlenbo79@gmail.com> Co-authored-by: Paul Thies <110185070+ImScheinox@users.noreply.github.com> Co-authored-by: lancetm714 <108419425+lancetm714@users.noreply.github.com> Co-authored-by: Lance Martin <lancetaylor95@gmail.com>
This commit is contained in:
@@ -49,6 +49,29 @@ export async function verifyScrypt(password: string, stored: string): Promise<bo
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A well-formed hash with a random salt and a random digest, drawn once per
|
||||
* process. No password matches it (the odds are 2^-512), so verifying against
|
||||
* it costs exactly what a real verification costs and always fails.
|
||||
*/
|
||||
const DUMMY_HASH = `${SCRYPT_PREFIX}${crypto.randomBytes(16).toString('hex')}:${crypto
|
||||
.randomBytes(64)
|
||||
.toString('hex')}`;
|
||||
|
||||
/**
|
||||
* Spend one scrypt verification on nothing.
|
||||
*
|
||||
* A password check that returns early — no such key, a key without a password,
|
||||
* a plaintext password compared by HMAC — answers in a couple of milliseconds,
|
||||
* while a real scrypt hash takes tens. That gap tells anyone who times the
|
||||
* replies which keys hold a hashed password, even when the reply bodies are
|
||||
* identical. Callers run this on every path that would otherwise skip scrypt,
|
||||
* so every attempt costs the same.
|
||||
*/
|
||||
export async function burnScrypt(password: string): Promise<void> {
|
||||
await verifyScrypt(password, DUMMY_HASH);
|
||||
}
|
||||
|
||||
/** Produce a storable `scrypt:salt:hash_hex` string. */
|
||||
export async function generateScryptHash(password: string): Promise<string> {
|
||||
const salt = crypto.randomBytes(16).toString('hex');
|
||||
|
||||
Reference in New Issue
Block a user