Key Derivation (NIP-06)
Derivation Path
Nostr keys follow the path:m/44'/1237'/<accountIndex>'/0/0
- Purpose:
44'(BIP-44) - Coin Type:
1237'(Nostr) - Account:
0'(default),1',2', etc. - Change:
0(external) - Index:
0(first key)
Example Usage
NostrKeysProvider
TheNostrKeysProvider manages key derivation, caching, and account switching.
Provider Features
- Automatic key derivation from mnemonic on app startup
- SecureStore caching to avoid expensive re-derivation
- Multi-account support with
getKeysForAccount(index) - Mnemonic hash validation to detect mnemonic changes
- Integration with CocoManager for Cashu wallet sync
Implementation
Context API
Secure Storage
Key Caching Strategy
To avoid re-deriving keys on every app launch (which is expensive), Sovran caches derived keys in Expo SecureStore:Cache Validation
Cached keys are only used if the mnemonic hasn’t changed:Multi-Account Support
Account Switching
Sovran supports multiple Nostr identities derived from the same mnemonic:Profile Store Integration
TheprofileStore tracks which accounts have been created:
Use Case: Testing
Multi-account support is useful for:- Testing: Create separate accounts for testing without affecting your main identity
- Privacy: Use different identities for different contexts
- Business/Personal: Separate professional and personal Nostr activity
Initialization Flow
Here’s how Sovran initializes Nostr keys on app startup:1
Check SecureStore for mnemonic
Try to load the mnemonic from Expo SecureStore. If it doesn’t exist, check Redux as a fallback migration path.
2
Generate mnemonic if needed
If no mnemonic exists anywhere, generate a new 12-word BIP-39 mnemonic and store it in SecureStore.
3
Hash mnemonic for cache validation
Compute SHA-256 hash of the mnemonic to validate cached keys.
4
Check cache for derived keys
Look for cached Nostr keys and Cashu mnemonic in SecureStore for the current account index.
5
Derive keys if cache miss
If cache is invalid or missing, derive fresh keys using NIP-06 and BIP-32. This is the slow path.
6
Update cache in background
Store the newly derived keys in SecureStore for next time. This happens asynchronously.
7
Set keys in context
Expose the keys via
NostrKeysContext so components can access keys, cashuMnemonic, etc.8
Initialize CocoManager
Configure the Cashu wallet manager with the account index and Cashu mnemonic.
9
Register with profileStore
Add the pubkey to the profile store so it appears in account switcher.
Cashu Key Derivation
Sovran also derives a separate Cashu wallet mnemonic from the root mnemonic:Security Best Practices
Never log private keys
Never log private keys
Validate mnemonic before use
Validate mnemonic before use
Check keys before operations
Check keys before operations
Clear sensitive data from memory
Clear sensitive data from memory
While JavaScript doesn’t provide explicit memory management, avoid storing private keys in long-lived variables:
Migration from Redux
Older versions of Sovran stored mnemonics in Redux. TheNostrKeysProvider automatically migrates:
- Detects no mnemonic in SecureStore
- Checks Redux for a fallback
- Migrates the mnemonic to SecureStore
- Derives and caches keys as normal
Testing
Test Vectors
Use known test mnemonics to verify correct derivation:Mock Provider
For component tests, mock theNostrKeysProvider:
Related Documentation
Direct Messages
Use derived keys to send encrypted NIP-17 messages
User Profiles
Publish profile metadata for your Nostr identity
Lightning Address
Claim a Lightning address for your npub
Secure Storage
Learn about Expo SecureStore and encryption