diff --git a/book/snippets/nostr/js/index.js b/book/snippets/nostr/js/index.js index bd7065850..d505db460 100644 --- a/book/snippets/nostr/js/index.js +++ b/book/snippets/nostr/js/index.js @@ -4,6 +4,7 @@ const eventBuilder = require("./src/event/builder"); const relayMessages = require("./src/messages/relay"); const nip01 = require("./src/nip01"); const nip05 = require("./src/nip05"); +const nip06 = require("./src/nip06"); const nip19 = require("./src/nip19"); const nip21 = require("./src/nip21"); const nip44 = require("./src/nip44"); @@ -23,6 +24,7 @@ async function main() { nip01.run(); await nip05.run(); + nip06.run(); nip19.run(); nip21.run(); nip44.run(); diff --git a/book/snippets/nostr/js/package.json b/book/snippets/nostr/js/package.json index 6ae5784ba..b4d7ca8b3 100644 --- a/book/snippets/nostr/js/package.json +++ b/book/snippets/nostr/js/package.json @@ -5,6 +5,7 @@ "main": "index.js", "license": "MIT", "dependencies": { - "@rust-nostr/nostr": "0.35.0" + "@rust-nostr/nostr": "0.35.0", + "bip39": "^3.1.0" } } diff --git a/book/snippets/nostr/js/src/nip06.js b/book/snippets/nostr/js/src/nip06.js new file mode 100644 index 000000000..620f94b50 --- /dev/null +++ b/book/snippets/nostr/js/src/nip06.js @@ -0,0 +1,77 @@ +const { loadWasmSync, Keys} = require("@rust-nostr/nostr"); +const { generateMnemonic } = require("bip39"); + +function run() { + // Load WASM + loadWasmSync(); + + console.log(); + // ANCHOR: keys-from-seed24 + // 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()}`); + // ANCHOR_END: keys-from-seed24 + + + console.log(); + // ANCHOR: keys-from-seed12 + // 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()}`); + // ANCHOR_END: keys-from-seed12 + + console.log(); + // ANCHOR: keys-from-seed-accounts + // 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}`); + } + // ANCHOR_END: keys-from-seed-accounts + + + console.log(); + // ANCHOR: keys-from-seed-accounts-pass + // 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}`); + } + // ANCHOR_END: keys-from-seed-accounts-pass +} + +module.exports.run = run; \ No newline at end of file diff --git a/book/src/nostr/06-nip06.md b/book/src/nostr/06-nip06.md index ca155bfca..1b1e2a7a9 100644 --- a/book/src/nostr/06-nip06.md +++ b/book/src/nostr/06-nip06.md @@ -56,7 +56,33 @@ It illustrates the effect of inclusion of a passphrase on the key derivation.
JavaScript
-TODO +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](https://github.com/bitcoinjs/bip39) package, a commonly used JavaScript implementation of Bitcoin BIP39, to randomly generate example seed phrases. + +```python,ignore +{{#include ../../snippets/nostr/js/src/nip06.js:keys-from-seed24}} +``` + +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. + +```python,ignore +{{#include ../../snippets/nostr/js/src/nip06.js:keys-from-seed12}} +``` + +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. + +```python,ignore +{{#include ../../snippets/nostr/js/src/nip06.js:keys-from-seed-accounts}} +``` + +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. + +```python,ignore +{{#include ../../snippets/nostr/js/src/nip06.js:keys-from-seed-accounts-pass}} +```