docs(rust,nodejs): expand TUTORIAL.md recovery-phrase section
Reworks the "Pick your primary key" → Option B block in both tutorials
into a proper "Recovery phrases" mini-chapter:
• Table comparing 24-word (256 bits, bijection) vs 12-word (128 bits,
one-way SHA-256 derivation).
• Decision guide — why someone would actually pick 12 over 24 (and
vice versa). Explicitly: "save the phrase, not just the seed" for
the 12-word case.
• Wallet-incompatibility callout — KEZ phrases don't produce the
same key as the same phrase in Ledger / MetaMask / Bitcoin
wallets. Explains the two deliberate reasons (no BIP-39 PBKDF2,
no BIP-32 derivation tree), and the inverse — KEZ phrases can't be
used to extract funds from a hardware-wallet recovery so a
malicious importer can't phish that direction either.
• Concrete backup advice — pencil on paper, numbered words, fireproof
storage, don't photograph it, don't cloud-sync it, don't split it,
don't permute it. Calls out which password-manager patterns are
OK vs not.
• "Working with phrases later" — clean examples of `identity mnemonic`
(no key derived) and `identity from-mnemonic` (recover an existing
key), with the note that the recovered output is byte-for-byte
identical to what `identity new` originally printed.
Same content in both the Rust and Node tutorials, command examples
adapted to each CLI invocation style.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
parent
5ad47a917d
commit
aeba28d9e5
@ -97,8 +97,8 @@ A new nostr keypair:
|
||||
npm run cli -- identity new
|
||||
```
|
||||
|
||||
Or a new Ed25519 keypair, which comes with a 24-word BIP-39 phrase
|
||||
alongside the hex seed (both are equivalent backups):
|
||||
Or a new Ed25519 keypair, which comes with a BIP-39 phrase alongside
|
||||
the hex seed (both are equivalent backups):
|
||||
|
||||
```sh
|
||||
npm run cli -- identity new --key-type ed25519 # 24-word
|
||||
@ -114,25 +114,107 @@ Secret: 9e3f51… (32-byte seed)
|
||||
Mnemonic (24 words): "abandon ability able about above absent academy accident…"
|
||||
```
|
||||
|
||||
> **12 vs 24.** 24 words is fully round-trippable: phrase ↔ seed are
|
||||
> bijective. 12 words is shorter to memorize, but the seed is derived
|
||||
> from the phrase one-way (KEZ-specific SHA-256 step), so you cannot
|
||||
> derive a 12-word phrase from a hex seed. Pick whichever you'll
|
||||
> actually back up.
|
||||
|
||||
You can also get just a phrase, or restore an existing one:
|
||||
|
||||
```sh
|
||||
npm run cli -- identity mnemonic # fresh 24 words
|
||||
npm run cli -- identity mnemonic --words 12 # fresh 12 words
|
||||
npm run cli -- identity from-mnemonic "abandon ability able …" # recover the key
|
||||
```
|
||||
|
||||
> **Save the backup.** Seed *or* phrase — at least one. Lose them both
|
||||
> and the identity is gone. There's no recovery flow.
|
||||
|
||||
### Recovery phrases — what's actually going on
|
||||
|
||||
A KEZ recovery phrase is a [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
|
||||
mnemonic — the same 2048-word English wordlist that Bitcoin, Ethereum,
|
||||
and most hardware wallets use. The words encode random bits:
|
||||
|
||||
| Phrase length | Random bits | Resulting Ed25519 seed |
|
||||
|---|---|---|
|
||||
| **24 words** | 256 bits of entropy | The 32-byte seed *is* those 256 bits (1:1). Phrase ↔ seed round-trips. |
|
||||
| **12 words** | 128 bits of entropy | 16 bytes → 32-byte seed via `SHA-256("kez-bip39-12-v1" \|\| entropy)`. Phrase → seed only (one-way). |
|
||||
|
||||
#### Picking 12 vs 24
|
||||
|
||||
- **Pick 24 words** when you want full round-trip-ability — i.e. you'd
|
||||
like to be able to *recover the phrase from the hex seed* at any time
|
||||
in the future. Anyone's 32-byte Ed25519 secret can be re-encoded into
|
||||
the unique 24-word phrase that produced it. Bigger security margin
|
||||
(256 bits of entropy vs 128).
|
||||
- **Pick 12 words** when you want a shorter thing to write down on
|
||||
paper or remember. 128 bits of entropy is still enormously beyond
|
||||
brute-forcing. The trade-off: the path is *one-way only* — you can
|
||||
always derive the seed from the phrase, but you cannot derive the
|
||||
phrase from the seed. So if you only ever have the seed, you'll
|
||||
never know what 12-word phrase produced it. **Save the phrase
|
||||
itself**, not just the resulting seed.
|
||||
|
||||
Either way the resulting Ed25519 identity is exactly the same shape;
|
||||
peers can't tell which word count you used. The choice is purely about
|
||||
your backup ergonomics.
|
||||
|
||||
#### ⚠ Not compatible with hardware-wallet derivations
|
||||
|
||||
A KEZ 12-word phrase **does not** produce the same Bitcoin or Ethereum
|
||||
key as the same 12 words typed into a Ledger or MetaMask, and vice
|
||||
versa. The reasons are deliberate:
|
||||
|
||||
1. Other wallets feed the phrase through BIP-39's PBKDF2 to get a
|
||||
64-byte "seed", then run that through BIP-32 hierarchical
|
||||
derivation at a coin-specific path. KEZ doesn't — it takes the
|
||||
raw entropy and uses it directly (24-word case) or hashes it with
|
||||
a domain tag (12-word case).
|
||||
2. KEZ identities aren't part of a derivation tree. There's one
|
||||
identity per phrase; there's no path component.
|
||||
|
||||
That means: **don't paste your existing hardware-wallet recovery
|
||||
phrase into KEZ** expecting to get a key you've already seen. It'll
|
||||
produce a *new* KEZ identity uncorrelated with anything else.
|
||||
|
||||
Conversely: a KEZ phrase you saved is *only* useful for KEZ. A
|
||||
malicious wallet that says "import this phrase" can't extract your
|
||||
existing Bitcoin / Ethereum funds from a KEZ phrase, because the
|
||||
phrase wasn't derived through the same path.
|
||||
|
||||
#### Backing up — concrete advice
|
||||
|
||||
The phrase is the master key to your identity. Practical guidance:
|
||||
|
||||
- **Write it on paper, with a pencil. Number each word (1–12 or 1–24)
|
||||
so you can later verify the order.** A photograph or cloud document
|
||||
is one breach away from compromise.
|
||||
- **Store the paper somewhere fireproof.** Safe-deposit boxes, lockable
|
||||
desk drawers, etched-stainless-steel cards if you're paranoid.
|
||||
- **Never type the phrase into a website, chat app, or password
|
||||
manager that auto-syncs.** Local-only password managers (KeePassXC,
|
||||
1Password locked vault) are OK; cloud-synced managers are a softer
|
||||
target.
|
||||
- **Don't split it across two locations "for safety".** Half a BIP-39
|
||||
phrase weakens the entropy more than it protects against loss. If you
|
||||
need redundancy, make two complete paper copies in different physical
|
||||
locations.
|
||||
- **Don't be cute.** Don't permute the words "because they're easy to
|
||||
remember in this order." The wordlist position matters; reorder and
|
||||
you change the key (and the BIP-39 checksum will reject it on
|
||||
restore anyway).
|
||||
|
||||
### Working with phrases later
|
||||
|
||||
You can generate a fresh phrase without producing a key, or recover
|
||||
the key from a phrase you wrote down earlier:
|
||||
|
||||
```sh
|
||||
# Print a fresh 24-word phrase (or 12, with --words 12). No key derived.
|
||||
npm run cli -- identity mnemonic
|
||||
npm run cli -- identity mnemonic --words 12
|
||||
|
||||
# Recover the Ed25519 key from a phrase. Word count auto-detected.
|
||||
npm run cli -- identity from-mnemonic "abandon ability able about above absent
|
||||
academy accident account accuse achieve acid acoustic acquire across act
|
||||
action actor actress actual adapt add addict address"
|
||||
```
|
||||
|
||||
The recovered output is identical, byte-for-byte, to what was printed
|
||||
when you first ran `identity new` — same `Primary:`, same `Public:`,
|
||||
same `Secret:`.
|
||||
|
||||
Throughout the rest of this tutorial you can substitute
|
||||
`--mnemonic "your phrase here"` anywhere `--ed25519-seed <hex>` appears.
|
||||
Both are accepted on every command that takes a signing key.
|
||||
|
||||
For the rest of this tutorial we'll use a nostr key for examples and
|
||||
write the secret as `nsec1FAKE...` — substitute your real one.
|
||||
|
||||
114
rust/TUTORIAL.md
114
rust/TUTORIAL.md
@ -81,7 +81,8 @@ kez identity new --key-type nostr # only if you want a NEW key
|
||||
|
||||
### Option B: generate a fresh Ed25519 primary
|
||||
|
||||
If you'd rather start clean, generate a new Ed25519 key:
|
||||
If you'd rather start clean, generate a new Ed25519 key with a BIP-39
|
||||
recovery phrase you can write down on paper:
|
||||
|
||||
```sh
|
||||
kez identity new --key-type ed25519 # 24-word phrase (default)
|
||||
@ -101,26 +102,107 @@ You now have **two equivalent backups** — the hex seed *and* the 24-word
|
||||
BIP-39 phrase. Either restores the same identity. Most people back up
|
||||
the phrase (easier to write down, easier to verify by hand).
|
||||
|
||||
> **12 vs 24.** 24 words is fully round-trippable: phrase ↔ seed are
|
||||
> bijective. 12 words is shorter to memorize, but the seed is derived
|
||||
> from the phrase one-way (KEZ-specific SHA-256 step), so you cannot
|
||||
> derive a 12-word phrase from a hex seed. Pick whichever you'll
|
||||
> actually remember to back up.
|
||||
|
||||
You can also get just a phrase without a key, or restore from a phrase
|
||||
you wrote down earlier:
|
||||
|
||||
```sh
|
||||
kez identity mnemonic # print a fresh 24-word phrase
|
||||
kez identity mnemonic --words 12 # 12-word
|
||||
kez identity from-mnemonic "abandon ability able …" # recover the key
|
||||
```
|
||||
|
||||
> **Save the backup.** Seed *or* phrase — at least one. Lose them both
|
||||
> and the identity is gone. There's no recovery flow.
|
||||
|
||||
### Recovery phrases — what's actually going on
|
||||
|
||||
A KEZ recovery phrase is a [BIP-39](https://github.com/bitcoin/bips/blob/master/bip-0039.mediawiki)
|
||||
mnemonic — the same 2048-word English wordlist that Bitcoin, Ethereum,
|
||||
and most hardware wallets use. The words encode random bits:
|
||||
|
||||
| Phrase length | Random bits | Resulting Ed25519 seed |
|
||||
|---|---|---|
|
||||
| **24 words** | 256 bits of entropy | The 32-byte seed *is* those 256 bits (1:1). Phrase ↔ seed round-trips. |
|
||||
| **12 words** | 128 bits of entropy | 16 bytes → 32-byte seed via `SHA-256("kez-bip39-12-v1" \|\| entropy)`. Phrase → seed only (one-way). |
|
||||
|
||||
#### Picking 12 vs 24
|
||||
|
||||
- **Pick 24 words** when you want full round-trip-ability — i.e. you'd
|
||||
like to be able to *recover the phrase from the hex seed* at any time
|
||||
in the future. Anyone's 32-byte ed25519 secret can be re-encoded into
|
||||
the unique 24-word phrase that produced it. Bigger security margin
|
||||
(256 bits of entropy vs 128).
|
||||
- **Pick 12 words** when you want a shorter thing to write down on
|
||||
paper or remember. 128 bits of entropy is still enormously beyond
|
||||
brute-forcing. The trade-off: the path is *one-way only* — you can
|
||||
always derive the seed from the phrase, but you cannot derive the
|
||||
phrase from the seed. So if you only ever have the seed, you'll
|
||||
never know what 12-word phrase produced it. **Save the phrase
|
||||
itself**, not just the resulting seed.
|
||||
|
||||
Either way the resulting Ed25519 identity is exactly the same shape;
|
||||
peers can't tell which word count you used. The choice is purely about
|
||||
your backup ergonomics.
|
||||
|
||||
#### ⚠ Not compatible with hardware-wallet derivations
|
||||
|
||||
A KEZ 12-word phrase **does not** produce the same Bitcoin or Ethereum
|
||||
key as the same 12 words typed into a Ledger or MetaMask, and vice
|
||||
versa. The reasons are deliberate:
|
||||
|
||||
1. Other wallets feed the phrase through BIP-39's PBKDF2 to get a
|
||||
64-byte "seed", then run that through BIP-32 hierarchical
|
||||
derivation at a coin-specific path. KEZ doesn't — it takes the
|
||||
raw entropy and uses it directly (24-word case) or hashes it with
|
||||
a domain tag (12-word case).
|
||||
2. KEZ identities aren't part of a derivation tree. There's one
|
||||
identity per phrase; there's no path component.
|
||||
|
||||
That means: **don't paste your existing hardware-wallet recovery
|
||||
phrase into KEZ** expecting to get a key that you've already seen.
|
||||
It'll produce a *new* KEZ identity uncorrelated with anything else.
|
||||
|
||||
Conversely: a KEZ phrase you saved is *only* useful for KEZ. A
|
||||
malicious wallet that says "import this phrase" can't extract your
|
||||
existing Bitcoin / Ethereum funds from a KEZ phrase, because the
|
||||
phrase wasn't derived through the same path.
|
||||
|
||||
#### Backing up — concrete advice
|
||||
|
||||
The phrase is the master key to your identity. Practical guidance:
|
||||
|
||||
- **Write it on paper, with a pencil. Number each word (1–12 or 1–24)
|
||||
so you can later verify the order.** A photograph or cloud document
|
||||
is one breach away from compromise.
|
||||
- **Store the paper somewhere fireproof.** Safe-deposit boxes, lockable
|
||||
desk drawers, etched-stainless-steel cards if you're paranoid.
|
||||
- **Never type the phrase into a website, chat app, or password
|
||||
manager that auto-syncs.** Local-only password managers (KeePassXC,
|
||||
1Password locked vault) are OK; cloud-synced managers are a softer
|
||||
target.
|
||||
- **Don't split it across two locations "for safety".** Half a BIP-39
|
||||
phrase weakens the entropy more than it protects against loss. If you
|
||||
need redundancy, make two complete paper copies in different physical
|
||||
locations.
|
||||
- **Don't be cute.** Don't permute the words "because they're easy to
|
||||
remember in this order." The wordlist position matters; reorder and
|
||||
you change the key (and the BIP-39 checksum will reject it on
|
||||
restore anyway).
|
||||
|
||||
### Working with phrases later
|
||||
|
||||
You can generate a fresh phrase without producing a key, or recover
|
||||
the key from a phrase you wrote down earlier:
|
||||
|
||||
```sh
|
||||
# Print a fresh 24-word phrase (or 12, with --words 12). No key derived.
|
||||
kez identity mnemonic
|
||||
kez identity mnemonic --words 12
|
||||
|
||||
# Recover the Ed25519 key from a phrase. Word count auto-detected.
|
||||
kez identity from-mnemonic "abandon ability able about above absent academy
|
||||
accident account accuse achieve acid acoustic acquire across act action
|
||||
actor actress actual adapt add addict address"
|
||||
```
|
||||
|
||||
The recovered output is identical, byte-for-byte, to what was printed
|
||||
when you first ran `identity new` — same `Primary:`, same `Public:`,
|
||||
same `Secret:`.
|
||||
|
||||
Throughout the rest of this tutorial you can substitute
|
||||
`--mnemonic "your phrase here"` anywhere `--ed25519-seed <hex>` appears.
|
||||
Both are accepted on every command that takes a signing key.
|
||||
|
||||
For the rest of this tutorial we'll use a nostr key for examples and
|
||||
write the secret as `nsec1FAKE...` — substitute your real one.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user