Monero Seed Tool

Offline seed & address inspector for Monero, modelled on Ian Coleman's BIP39 Mnemonic Code Converter and bitcoiner.guide/seed. Single file, no dependencies, no network access.

Download for offline use

Seed

Notes

Polyseed

Polyseed is the newer Monero seed format. It is 16 words long and, besides the secret, it stores the wallet's birthday, so a restoring wallet knows where to start scanning the blockchain. The words come from the 2048-word BIP39 English list (the first 4 letters of each word are unique), but it is not a BIP39 seed.

How it is built: each word stands for an 11-bit number, so the 16 words hold 176 bits.

From seed to spend key: the secret is stretched with PBKDF2-HMAC-SHA256 (10 000 rounds) using a salt that contains "POLYSEED key", the coin, the birthday and the features. The 32-byte result, reduced mod l, is the private spend key. So the birthday and features are part of the key: change them and you get a different wallet. Because PBKDF2 is a one-way hash, a Polyseed can be turned into a 25-word seed (the tool shows it), but a 25-word seed or a spend key can never be turned into a Polyseed.

Encrypted Polyseeds: Polyseed has its own passphrase option. It mixes a PBKDF2 hash of the passphrase into the secret and sets the "encrypted" flag, so the wallet knows to ask for it. Monero wallets normally do not use this: a passphrase set when a Monero wallet is created is a seed offset (see below). The tool handles both. If the flag is set, the passphrase decrypts the seed straight away; if not, it is applied as a seed offset.

25-word seed

The original Monero seed format. Its words come from a 1626-word list (the first 3 letters of each word are unique). It is simply the private spend key written as words. It carries no birthday, so when restoring, give the wallet a restore height or date, or it scans from the start of the blockchain.

How it is built:

  1. The 32-byte private spend key is split into 8 groups of 4 bytes.
  2. Each group is a number below 232 and is written as 3 words (16263 is just over 232). 8 × 3 = 24 words.
  3. The 25th word is a checksum: the first 3 letters of the 24 words are joined, a CRC-32 of that text is taken, and the result mod 24 picks which of the 24 words is repeated at the end.

Because it is a direct encoding, it works both ways: every spend key has exactly one 25-word seed, and back.

Seed offset

A seed offset is an optional passphrase that turns one seed into a different wallet. The seed words do not change and the passphrase is not stored anywhere, so you need both to restore the wallet. It works the same way for 25-word seeds and Polyseeds.

How it works: the passphrase is hashed with CryptoNight (cn_slow_hash, variant 0), a deliberately slow hash with a 2 MB scratchpad. It takes a few seconds, so the tool waits until you press Apply offset or Enter. The 32-byte hash is subtracted from the seed's spend key mod l; the result is the wallet's real spend key, and all other keys follow from it. The passphrase is used exactly as typed: capitals, spaces and accents all count.

A passphrase cannot be checked: every passphrase gives a valid, different wallet. That allows a decoy wallet (the same seed without the offset), but a typo or a forgotten passphrase silently leads to a different, empty wallet.

Keys

A Monero wallet has two key pairs, and all four keys follow from the private spend key. That is why the seed alone restores everything.

Addresses: the primary address is a network byte, B, A and a 4-byte Keccak-256 checksum, written in Monero's base58 (95 characters). The network byte sets the first character: 4 on mainnet, 5 on stagenet, 9 on testnet. The keys are the same on every network; only the addresses change.

Subaddresses: account i, index j uses m = Keccak-256("SubAddr\0" ‖ a ‖ i ‖ j) mod l, D = B + m·G and C = a·D, encoded like an address with a different network byte, so they start with 8 / 7 / B. Index 0/0 is the primary address itself. All subaddresses belong to the same wallet, but nobody else can tell that they are linked. An integrated address (deprecated) is the primary address with an 8-byte payment ID added.

Dice rolls

Use at least 100 rolls of a fair six-sided die (about 258 bits). The rolls are read as one base-6 number, first roll most significant. For a 25-word seed, the low 256 bits are reduced mod l and become the spend key. For a Polyseed, the low 150 bits become the secret, with the birthday set to the current month from this computer's clock and no features; the same rolls entered in another month give a different Polyseed. The two seed types use the rolls differently, so the same rolls make two unrelated wallets.

Random seeds

Random Polyseed: 150 random bits from the browser's cryptographic random generator, with the birthday set to the current month from this computer's clock. Random 25-word seed: 32 random bytes from the same generator, reduced mod l, the standard way a new Monero spend key is made.

Limitations

Not supported: Polyseeds in languages other than English, 13-word seeds, and hardware-wallet seeds (BIP39 seeds with a different key derivation). The maths uses JavaScript BigInt and is not constant-time. That is fine on your own offline computer, but this is not a hardened wallet: never enter the seed of real funds on a computer that is online or shared.