Skip to content

[New Feature] Derive Nostr privkey / pubkey via NIP-06 #744

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: dev
Choose a base branch
from

Conversation

kdmukai
Copy link
Contributor

@kdmukai kdmukai commented Apr 23, 2025

Background

I originally built a full nostr integration for the 2023 Nostrica conference. That branch was always meant to just be a fun demo and a conversation starter (primarily around NIP-26 delegated signing). It was not intended to ever be PRed into the main SeedSigner repo.

However, the NIP-06 key derivation portions are actually broadly useful.

What is nostr

see: https://nostr.org/

What is NIP-06

see: https://github.com/nostr-protocol/nips/blob/master/06.md

It's a very simple BIP-32 derivation of a new privkey / pubkey pair using the specified derivation path. From there you can generate your nsec/npub for use in nostr clients. The nostr hex key formats are also trivially generated.

Nostr client support

Nostr clients have varying support for NIP-06 (either presenting the user with a BIP-39 mnemonic backup for a newly created nostr key or importing from a BIP-39 mnemonic to restore your nostr key).

But for purposes, NIP-06 integration isn't even necessary. Every nostr client or remote signer will support keys entered as nsec or hex format. And at least one, Amber, can read keys in via QR. I haven't exhaustively researched which other clients and apps support QR. I would assume others exist and, given the pace of nostr development, I'm sure other clients could add QR support quickly if there was enough interest.

This PR

Rationale

SeedSigner and nostr have always been aligned in the FOSS and self-sovereignty ethos. We can encourage and facilitate using BIP-39 mnemonics as the backup format for nostr keys, which by itself is a big win. And leveraging SeedSigner's bring-your-own-entropy seed creation as part of a user's Nostr key creation flow is another big win.

Also, new developments such as Frostr (literally FROST + nostr) possibly lend themselves to more offline key creation features that could some day be built into SeedSigner.

Details

I've refactored some of that original Nostrica demo code and stripped out everything except the NIP-06 key derivation features.

Creates a new Settings option (disabled by default) to add Nostr key export as an option for a given Seed.

SettingsMenuView__Advanced SettingsEntryUpdateSelectionView_nostr_nip06_export


SeedOptionsView NostrKeyExportStartView NostrKeyExportSelectTypeView


If you select one of the privkey formats:

NostrKeyExportPrivateKeyWarningView


NostrExportKeyDisplayKeyView__npub NostrExportKeyDisplayKeyView__nsec NostrExportKeyDisplayKeyView__privkey_hex

After this screen the nostr privkey or pubkey is displayed as a static QR.


Related changes

I opted to isolate the nostr functionality in its own:

  • helpers.nostr
  • views.nostr_views
  • screens.nostr_screens

Minimal touchpoints to the rest of the code. Just the necessary integrations in SeedOptionsView, Settings, screenshot generator.

Full unit tests and flow tests added.

Updated messages.pot master translation file for the new nostr-related display strings.

Note the obvious color scheme violation with the nostr-themed purple in the final display screen. As always I defer to @easyuxd if this indulgence should be allowed. My argument: it's a fun, harmless one-off that's buried deep in a specific flow that's disabled by default. But I will accept Easy's decision either way without gripe.


This pull request is categorized as a:

  • New feature

Checklist

  • I’ve run pytest and made sure all unit tests pass before sumbitting the PR

If you modified or added functionality/workflow, did you add new unit tests?

  • Yes

I have tested this PR on the following platforms/os:

@newtonick
Copy link
Collaborator

newtonick commented Apr 24, 2025

Concept NACK

The primary value of this enhancement is using the SeedSigner camera as a source of entropy for private key material. Private key material created on SeedSigner would still need to be exported to an internet connected signing device. Typically a user would use a phone to scan the QR to get their nsec. I dislike normalizing the scanning private key material of any kind from a SeedSigner device (even with warning dialogs).

This would also be a new milestone for the SeedSigner app repo. SeedSigner would no longer be a Bitcoin only device.

This said, if there is enough contributor support for this enhancement, I’m willing to merge with review and testing.

@simongltr
Copy link

I understand the point of @newtonick but as a user I really want my signer to be a source of entropy not only for Bitcoin but also for passwords and Nostr keys.

I'm currently generating my Nostr accounts with BIP85 32 bytes hex strings from my Coldcard, then I convert to the nsec format using the following script:

from secp256k1 import PrivateKey
from bech32 import bech32_encode as enc, convertbits as cb
import sys
if len(sys.argv) != 2:
    print("Usage: python3 derive.py <bip85_32_bytes_hex_entropy>")
    sys.exit(1)
key = PrivateKey(privkey=bytes.fromhex(sys.argv[1]))
nsec = enc("nsec", cb(key.private_key, 8, 5))
npub = enc("npub", cb(key.pubkey.serialize()[1:], 8, 5))
print(f"nsec: {nsec}\nnpub: {npub}")

I would love to either have this NIP06 implementation or more BIP85 options to generate hex strings, with optionally a "Vew as nsec" button.

I find this NIP06 demo really well done. Combined with the fact that this feature is opt-in, I fully support this PR (though I didn’t check the code).

@newtonick
Copy link
Collaborator

@simongltr I appreciate your feedback.

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.

3 participants