PCH-02-005-legacy-pbkdf2-doc.patch.md

4.3 KB · raw

rendered · source

PCH-02-005 — Document the legacy PBKDF2 import KDF + recommend re-export

Severity: Informational Target files: src/shared/backup.ts:146 (derivePeachExportKey), src/popup/views/Import.tsx (re-export notice) Report: peach-code-review.md, Finding PCH-02-005

Correction to the fix brief

The brief's comment text says "100,000 iterations". The code (and the report) say 250,000 (backup.ts:166). The comment below uses the value the code actually enforces — a comment that misstates its own parameters is worse than no comment.

Edit 1 — KDF comment at backup.ts:146

// BEFORE (backup.ts:146-150)
export async function derivePeachExportKey(
  password: string,
  salt: Uint8Array,
  opts: { raw?: boolean } = {}
): Promise<Uint8Array> {

// AFTER
/**
 * LEGACY IMPORT KDF (PCH-02-005):
 * This path derives with PBKDF2-SHA256 (250,000 iterations) for backwards
 * compatibility with `.json` exports sealed before the Argon2id migration —
 * the encrypted-JSON export UI was removed in v2.5.0 (see header), so this
 * KDF is import-only (plus the test fixture generator above).
 *
 * PBKDF2 has no memory-hardness and is materially weaker than the current
 * Argon2id envelope (m=64 MiB, t=3, p=4 — peachPayload.ts) against GPU/ASIC
 * attackers at equal wall-clock cost. Do NOT use this helper for any new
 * format. Users importing an old `.json` backup are prompted to export a
 * fresh backup afterwards (Import.tsx legacy-KDF notice).
 */
export async function derivePeachExportKey(
  password: string,
  salt: Uint8Array,
  opts: { raw?: boolean } = {}
): Promise<Uint8Array> {

(The existing LV-1 NFC comment inside the function body stays as is.)

Edit 2 — post-import re-export notice in Import.tsx

Verified: there is currently no user-facing recommendation after a successful PBKDF2 (peach-json) import. The import success path keeps the view mounted and already surfaces a post-import duplicateWarning notice (Import.tsx:790) — the legacy-KDF notice mirrors that exact mechanism.

2a. Add a signal next to duplicateWarning (Import.tsx:~425):

// AFTER the existing line:
  const [duplicateWarning, setDuplicateWarning] = createSignal<number>(0);
// ADD:
  // PCH-02-005: set when a legacy PBKDF2-encrypted `.json` backup imports
  // successfully — prompts the user to re-export under the Argon2id format.
  const [legacyKdfNotice, setLegacyKdfNotice] = createSignal(false);

2b. In handleImport, alongside setDuplicateWarning(dupes) (the success tail, Import.tsx:~604):

// BEFORE
      setDuplicateWarning(dupes);
      await props.onImport();

// AFTER
      setDuplicateWarning(dupes);
      // PCH-02-005: "peach-json" is the legacy PBKDF2-SHA256 envelope; every
      // other recognised format is plaintext-source (no KDF) or current-format.
      setLegacyKdfNotice(currentPreview.format === "peach-json");
      await props.onImport();

Also reset it where the other notices reset (handleFileSelect, alongside setError(null) / setAwaitingReplaceConfirm(false)):

      setLegacyKdfNotice(false);

2c. Render next to the duplicate-warning block (Import.tsx:~790, same <Show> pattern and styling class as the sibling notice):

        <Show when={legacyKdfNotice() && !importing()}>
          <div class="peach-settings-group">
            <div class="peach-restore-warning">
              This backup was created with Peach's older encryption format
              (PBKDF2). It imported fine — but we recommend exporting a fresh
              backup now so your paper/file backups use the current, stronger
              format.
            </div>
          </div>
        </Show>

(Class choice: peach-restore-warning is the existing soft-warning surface used three blocks above; no new CSS.)

Tests

UI-notice coverage belongs in src/popup/views/contracts.test.tsx style; the notice is a pure render-state change. Suggested single contract case (optional, not counted as a security regression test): mock parseImportSource to return format: "peach-json", drive handleImport, assert the notice text renders. The KDF comment itself needs no test.

Save message (integration)

fix: PCH-02-005 document legacy PBKDF2 import path + recommend re-export after legacy import