NIP-06: Basic key derivation from mnemonic seed phrase
In accordance with the BIP-32 and BIP-39 we can derive Nostr keys using seed phrases as a source of entropy.
The default functionality is to generate a single key-pair at the derivation path 0
.
However, it is also possible to perform more advanced derivations by incrementing the account
,
enabling the generation of many sets of keys from a single mnemonic seed phrase.
TODO
Using the from_mnemonic()
method in conjunction with the Keys
class to derived a basic set of Nostr keys from a 24 word seed phrase.
Note that this example uses the Mnemonic
class from the python-mnemonic package (the reference implementation of BIP-39) to randomly generate example seed phrases.
# Generate random Seed Phrase (24 words e.g. 256 bits entropy)
print("Keys from 24 word Seed Phrase:")
words = Mnemonic("english").generate(strength=256)
passphrase = ""
# Use Seed Phrase to generate basic Nostr keys
keys = Keys.from_mnemonic(words, passphrase)
print(f" Seed Words (24) : {words}")
print(f" Public key bech32: {keys.public_key().to_bech32()}")
print(f" Secret key bech32: {keys.secret_key().to_bech32()}")
As well as deriving basic keys from a 24 word seed we can also use seed phrases of other lengths such as 18 words or, as in this example, 12 words.
# Generate random Seed Phrase (12 words e.g. 128 bits entropy)
print("Keys from 12 word Seed Phrase:")
words = Mnemonic("english").generate(strength=128)
passphrase = ""
# Use Seed Phrase to generate basic Nostr keys
keys = Keys.from_mnemonic(words, passphrase)
print(f" Seed Words (12) : {words}")
print(f" Public key bech32: {keys.public_key().to_bech32()}")
print(f" Secret key bech32: {keys.secret_key().to_bech32()}")
Advanced key derivation functionality (for accounts) can be accessed by the from_mnemonic()
method.
To do this we use the account
argument which accepts an integer to specify the derivation path.
# Advanced (with accounts) from the example wordlist
words = "leader monkey parrot ring guide accident before fence cannon height naive bean"
passphrase = ""
print("Accounts (0-5) from 12 word Seed Phrase (with passphrase):")
print(f" Seed Words (12): {words}")
print(" Accounts (0-5) :")
# Use Seed Phrase and account to multiple Nostr keys
for account in range(0,6):
nsec = Keys.from_mnemonic(words, passphrase, account).secret_key().to_bech32()
print(f" Account #{account} bech32: {nsec}")
This final example utilizes the same seed as for the previous example, but also includes a passphrase
.
It illustrates the effect of inclusion of a passphrase on the key derivation.
# Advanced (with accounts) from the same wordlist with in inclusion of passphrase
words = "leader monkey parrot ring guide accident before fence cannon height naive bean"
passphrase = "RustNostr"
print("Accounts (0-5) from 12 word Seed Phrase (with passphrase):")
print(f" Seed Words (12): {words}")
print(f" Passphrase : {passphrase}")
print(" Accounts (0-5) :")
# Use Seed Phrase and account to multiple Nostr keys
for account in range(0,6):
nsec = Keys.from_mnemonic(words, passphrase, account).secret_key().to_bech32()
print(f" Account #{account} bech32: {nsec}")
Using the fromMnemonic()
method in conjunction with the Keys
class to derived a basic set of Nostr keys from a 24 word seed phrase.
Note that this example uses the generateMnemonic()
method from the bip39 package, a commonly used JavaScript implementation of Bitcoin BIP39, to randomly generate example seed phrases.
// Generate random Seed Phrase (24 words e.g. 256 bits entropy)
let words256 = generateMnemonic(256);
console.log("Generated Random Seed Phrase and Derived Keys:");
console.log(`\t - Seed Words (24): ${words256}`);
let passphrase256 = "";
// Use Seed Phrase to generate basic Nostr keys
let keys256 = Keys.fromMnemonic(words256, passphrase256);
// Print Results
console.log(`\t - Private (hex) : ${keys256.secretKey.toHex()}`);
console.log(`\t - Private (nsec) : ${keys256.secretKey.toBech32()}`);
console.log(`\t - Public (hex) : ${keys256.publicKey.toHex()}`);
console.log(`\t - Public (npub) : ${keys256.publicKey.toBech32()}`);
As well as deriving basic keys from a 24 word seed we can also use seed phrases of other lengths such as 18 words or, as in this example, 12 words.
// Generate random Seed Phrase (12 words e.g. 128 bits entropy)
let words128 = generateMnemonic(128);
console.log("Generated Random Seed Phrase and Derived Keys:");
console.log(`\t - Seed Words (12): ${words128}`);
let passphrase128 = "";
// Use Seed Phrase to generate basic Nostr keys
let keys128 = Keys.fromMnemonic(words128, passphrase128);
// Print Results
console.log(`\t - Private (hex) : ${keys128.secretKey.toHex()}`);
console.log(`\t - Private (nsec) : ${keys128.secretKey.toBech32()}`);
console.log(`\t - Public (hex) : ${keys128.publicKey.toHex()}`);
console.log(`\t - Public (npub) : ${keys128.publicKey.toBech32()}`);
Advanced key derivation functionality (for accounts) can be accessed by the fromMnemonic()
method.
To do this we use the account
argument which accepts an integer to specify the derivation path.
// Advanced (with accounts) from the same wordlist
let words = "leader monkey parrot ring guide accident before fence cannon height naive bean";
let passphrase = "";
console.log("Generated Accounts:");
console.log(`\t - Seed Words (12): ${words}`);
// Use Seed Phrase and account to multiple Nostr keys
for (let account = 0; account < 6; account++) {
let nsec = Keys.fromMnemonic(words, passphrase, account).secretKey.toBech32();
console.log(`\t - Private (nsec) Account #${account}: ${nsec}`);
}
This final example utilizes the same seed as for the previous example, but also includes a passphrase
.
It illustrates the effect of inclusion of a passphrase on the key derivation.
// Advanced (with accounts) from the same wordlist with in inclusion of PassPhrase
words = "leader monkey parrot ring guide accident before fence cannon height naive bean";
passphrase = "RustNostr";
console.log("Generated Accounts:");
console.log(`\t - Seed Words (12): ${words}`);
// Use Seed Phrase, passphrase and account to multiple Nostr keys
for (let account = 0; account < 6; account++) {
let nsec = Keys.fromMnemonic(words, passphrase, account).secretKey.toBech32();
console.log(`\t - Private (nsec) Account #${account}: ${nsec}`);
}
TODO
TODO
TODO