Skip to content

fix(desktop): accept uppercase/mixed-case nsec in key import (#4247) - #4263

Open
iroiro147 wants to merge 1 commit into
block:mainfrom
iroiro147:fix/4247-uppercase-nsec
Open

fix(desktop): accept uppercase/mixed-case nsec in key import (#4247)#4263
iroiro147 wants to merge 1 commit into
block:mainfrom
iroiro147:fix/4247-uppercase-nsec

Conversation

@iroiro147

Copy link
Copy Markdown

What

The desktop onboarding key-import form told users pasting a valid nsec1… key that it was invalid whenever the encoding used uppercase letters — Bech32 permits an all-uppercase encoding (the checksum is identical regardless of case), and tools that emit printable/backup keys often uppercase them.

Issue #4247 reports users hitting "Waiting for a valid nsec1 key" / "Invalid key" on keys that other Nostr clients accept.

Root cause

Two case-sensitive HRP/prefix checks:

  1. shared/lib/nostrUtils.ts:nsecToNpub compared trimmed.startsWith("nsec1") before calling nostr-tools/nip19.decode(). Uppercase input failed the prefix check; mixed-case made it to decode() and rejected by the spec-compliant checksum library.
  2. features/onboarding/lib/keyImportInput.ts:classifyKeyImportInput already lowercased the longer ncryptsec1 HRP but kept trimmed.startsWith("nsec1") case-sensitive, so an uppercase NSEC1… classified as "unknown" and the form showed the unencrypted-error path.

Changes

  • nsecToNpub: lowercases after trim() before both the prefix check and decode(). Whitespace tolerance is unchanged. The parser is intentionally permissive on casing — a copy-paste that damaged only case should still resolve rather than reject the user.
  • classifyKeyImportInput: mirrors the existing ncryptsec1 lowercase-slice pattern for nsec1 so an uppercase key is classified as "nsec" and npub preview / submit gating continue down the correct path.

Corrupted checksums, non-nsec inputs, and empty strings still reject exactly as before.

Tests

New src/shared/lib/nostrUtils.test.mjs (6 cases):

  • lowercase nsec resolves to an npub
  • uppercase encoding resolves identically to lowercase
  • surrounding whitespace tolerated
  • checksum corruption rejects
  • mixed-case resolves tolerantly (deliberate — spec-strict reject was the bug)
  • non-nsec inputs reject

Extended src/features/onboarding/lib/keyImportInput.test.mjs:

  • uppercase nsec classifies as "nsec" and submit-enables without a passphrase

Receipts: 12/12 nostrUtils+keyImportInput tests pass; 238/238 across the related onboarding+shared-lib suites; pnpm exec tsc --noEmit clean; ncryptsecSourceScan allowlist unaffected.

Linked issue

Refs #4247

)

The desktop key-import form told users pasting a valid nsec1… key that
it was invalid whenever the encoding used uppercase (or mixed-case)
letters. Bech32 permits an all-uppercase encoding, and tools that emit
printable/backup keys often uppercase them — the checksum is identical
regardless of case.

- nostrUtils.nsecToNpub: lowercase after trim before the prefix and
  checksum checks. Whitespace tolerance is unchanged.
- keyImportInput.classifyKeyImportInput: case-insensitive on the nsec1
  HRP, mirroring the existing ncryptsec1 handling, so the form picks
  the correct mode for an uppercase key.

Both paths continue to reject corrupted checksums and non-nsec inputs.
The parser is deliberately permissive on casing: a copy-paste that
damaged only case should still resolve rather than reject the user.

Regression coverage:
- onboarding/lib/keyImportInput.test.mjs — uppercase classify + submit
- shared/lib/nostrUtils.test.mjs (new) — lowercase / uppercase / mixed
  case / whitespace tolerance / checksum rejection / non-nsec rejection

Refs block#4247

Signed-off-by: Sarthak Singh <sarthak.singh@juspay.in>
@iroiro147
iroiro147 requested a review from a team as a code owner August 2, 2026 05:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant