fix(recovery): accept -v2 / argon2id verifiers in setup
/recovery-key/setup verified the master password with a local copy of the verifier check that only knew pbkdf2 (legacy) and pbkdf2-sha256. Any account on a decoupled scheme — pbkdf2-sha256-v2 or argon2id-v2, the current default after a master-pw rotation — fell through both branches and was rejected as "invalid password" even when correct, so recovery-key setup was impossible. Match the canonical VerifierToStoredHash (PM.Handler.Auth): legacy stores the verifier raw, every other algo is SHA256-wrapped identically. One branch, plus a keep-in-sync note so the copy doesn't drift again. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -82,11 +82,15 @@ begin
|
|||||||
|
|
||||||
if AVerifier <> '' then
|
if AVerifier <> '' then
|
||||||
begin
|
begin
|
||||||
// ZK: client computed PBKDF2 hex locally. Server only does the wrap.
|
// ZK: client computed the verifier locally. Server only wraps it — legacy
|
||||||
|
// pbkdf2 stores it raw, EVERY other algo (pbkdf2-sha256, pbkdf2-sha256-v2,
|
||||||
|
// argon2id-v2) is SHA256-wrapped identically. Mirrors VerifierToStoredHash
|
||||||
|
// in PM.Handler.Auth — keep in sync. The old `else if =CURRENT` silently
|
||||||
|
// rejected -v2 / argon2id accounts (the current default) as wrong-password.
|
||||||
if Length(AVerifier) <> 64 then Exit;
|
if Length(AVerifier) <> 64 then Exit;
|
||||||
if SameText(LAlgo, HASH_ALGO_LEGACY) then
|
if SameText(LAlgo, HASH_ALGO_LEGACY) then
|
||||||
Result := ConstantTimeEquals(AVerifier, LStoredHash)
|
Result := ConstantTimeEquals(AVerifier, LStoredHash)
|
||||||
else if SameText(LAlgo, HASH_ALGO_CURRENT) then
|
else
|
||||||
Result := ConstantTimeEquals(SHA256Hex(AVerifier), LStoredHash);
|
Result := ConstantTimeEquals(SHA256Hex(AVerifier), LStoredHash);
|
||||||
Exit;
|
Exit;
|
||||||
end;
|
end;
|
||||||
|
|||||||
Reference in New Issue
Block a user