Private keys and seed phrases are core to how we secure assets and verify identity on blockchains. Almost everyone in Web3 uses them, but few actually look under the hood to understand what makes them work or what risks they might carry.
Are private keys really secure? Could they be cracked by quantum computing in the near future?
This article kicks off the "A Shit Tonne About..." series, exploring into topics people often overlook or don’t bother to understand. This one is all about private keys and seed phrases.
For those unfamiliar, what the heck is a seed phrase?
When you set up a wallet to store your bitcoin or cryptocurrency whether it's a hardware wallet (like Trezor or Ledger) or a software wallet on your phone or computer you’re provided with a 12 or 24 word sequence in a specific order.
This sequence is known as your seed phrase (also called a recovery phrase, mnemonic phrase, or seed).
Your wallet likely instructed you to write this seed phrase down somewhere secure. If your wallet device is lost, damaged, or stolen, this seed phrase is the one element that allows you to restore and recover your wallet and funds on a new device. Note that both the words and their exact order are critical.
BIP 39 Seed Phrase
Your seed phrase is likely based on Bitcoin Improvement Proposal 39 (BIP 39). BIP 39 defines the use of a mnemonic phrase, a sequence of easily memorable words to derive the information required to access your coins.
Essentially, this process is how a wallet compresses all necessary recovery data into a 12- to 24-word phrase. The words in a BIP 39 seed phrase come from a fixed list of 2048 words, known as the BIP39 word list.
Most wallets follow the BIP 39 standard for generating a seed phrase, making it possible to import a seed phrase from one BIP 39 wallet to another. When setting up a new wallet, you’ll often have the option to import an existing seed phrase, allowing you to recover your wallet from another device.
If one wallet doesn’t support a specific coin, a compatible wallet that does can still use the same seed phrase to access your assets.
The Special Last Word of a Seed Phrase
You might think a seed phrase is just a collection of randomly selected words.
It is, but it also isn't.
The words in your seed phrase come from the BIP39 wordlist as discussed earlier, which contains 2048 commonly used words (with the exception of "satoshi").
In the BIP39 standard, the last word is unique. But what does that really mean?
The last word of a BIP39 seed phrase is referred to as a checksum (or part of it, to be precise).
The primary purpose of a checksum is to detect errors within a data set. In the context of a seed phrase, the last word ensures that your seed phrase adheres to the "rules" and structure defined by the BIP39 standard. This checksum is calculated based on the initial data used to generate your seed.
If you want to test this yourself, type any 12 to 24 words (not your actual seed) from the BIP39 wordlist into this tool. You’ll likely receive an error indicating that it is invalid.
for example, the below seed phrase
under suggest tone congress announce hospital syrup city scatter warfare announce subject
contains 12 words from the wordlist but still it is an invalid mnemonic
You might be wondering why a seed you created worked in a wallet you’ve used before. According to the BIP39 documentation, "Although using a mnemonic not generated by the algorithm described in the 'Generating the mnemonic' section is possible, this is not advised. Software must compute a checksum for the mnemonic sentence using a wordlist and issue a warning if it is invalid."
This means that a wallet won't outright reject an invalid seed; it may accept it but should provide a warning, which is at the developer's discretion.
So, you cannot simply choose any 12 to 24 words to create a valid seed phrase because the last word functions as a checksum. It is calculated using the data from the preceding words.
For a 24-word seed phrase, the last word can be one of eight potential options based on the previous 23 words.
For a 12-word seed phrase, the last word can be one of 128 potential options based on the preceding 11 words.
Can Someone Guess My Seed Phrase?
Is it possible? Yes.
But, consider this: winning the jackpot four times in a row is also possible.
So, is it probable? No. (In fact, you’re more likely to win the jackpot four times in a row than to guess a seed phrase.)
Number of Possible Seed Phrase Combinations
Your seed phrase is derived from a specific list of 2048 words. To access your wallet, someone would need to guess all the words and arrange them in the correct order.
For a 12-word seed phrase, there are approximately:
777,788,267,247,859,345,059,141,959,844,041,626,185 valid combinations.
(2048^11) * (2048/(11-4))
For a 24-word seed phrase, there are around:
1,976,184,989,650,196,401,895,611,477,481,606,960,695,807,738,293,598,959,606,742,767,068,384,079,188,241 valid combinations.
(2048^23) * (2048/(23-8))
These numbers are enormous. So large that they defy comprehension for most people. Let’s put this into perspective.
In practical terms, it’s far more likely that something else will occur than for someone to guess your seed phrase.
It’s more probable that your seed gets lost, destroyed unexpectedly, or stolen than that someone correctly guesses it.
Blockchain Bandit Guessing Private Keys
Adrian Bednarek, a security consultant, explored methods for stealing Ethereum. While working for a client in the troubled cryptocurrency sector, he discovered that a simple private key had once held currency according to the Ethereum blockchain. However, the funds had already been withdrawn, likely by a thief who had guessed the private key long before Bednarek's investigation began.
In a paper released recently, Bednarek and his team found that many cryptocurrency users have stored their assets using easily guessable private keys. They identified what they termed a "blockchain bandit" an Ethereum account that stole around 45,000 ether, valued at over $50 million at one point, using these weak keys.
In the process, and as detailed in a paper they published, the researchers not only found that cryptocurrency users have in the last few years stored their crypto treasure with hundreds of easily guessable private keys, but also uncovered what they call a "blockchain bandit." A single Ethereum account seems to have siphoned off a fortune of 45,000 ether—worth at one point more than $50 million using those same key.
To explain how that blockchain banditry works, it helps to understand that the the odds of guessing a randomly generated Ethereum private key is 1 in 115 quattuorvigintillion
.
As a fraction: 1/2^256
That denominator is very roughly around the number of atoms in the universe. So clearly it is pure luck that someone guesses your Private Key or Seed Phrase.
Now moving away from security for seed phrases let us look at how a seed phrase is created.
How a Seed Phrase is Created
Let's go through the process of creating a seed phrase step by step.
Let's Start with Entropy
A seed phrase starts with a concept called entropy.
What is entropy?
In the context of data, entropy refers to a measure of "randomness." Essentially, it represents a large random number that is highly unlikely to be generated again.
How is this random number generated? It can come from a secure device (like a computer without internet or other external connections) or from a physical process like flipping a coin (assigning heads=1 and tails=0). Regardless of the method, the randomness must be true.
For a seed phrase, this begins as a random binary number (composed of only 1s and 0s), such as:
11011010010000101100101111001001110010000111111000010010100000001100001101001100101001011110011111001000010001010110000101111111
Each 1 and 0 is called a bit, and this sequence of bits is referred to as our entropy. This example consists of 128 bits, which is needed for a 12-word seed phrase (or 256 bits for a 24-word seed phrase). This length is crucial for the next steps.
Now that we have our entropy, we will convert it into familiar words.
Now Let’s Make Some Numbers
Recall that the BIP39 wordlist contains 2048 words, each assigned a unique number based on alphabetical order (e.g., abandon = 1, ability = 2, ... zoo = 2048).
In binary, a set of 11 bits can represent a number from 0 to 2047.
To convert binary to a decimal number (the familiar number format), sum the values based on the position of each bit. The position determines whether to multiply a 0 or 1 by 2^n, where n is the descending positional index of the bit (starting from the total number of bits minus 1).
For example, to convert 11100101001 to decimal:
(2¹⁰ x 1) + (2⁹ x 1) + (2⁸ x 1) + (2⁷ x 0) + (2⁶ x 0) + (2⁵ x 1) + (2⁴ x 0) + (2³ x 1) + (2² x 0) + (2¹ x 0) + (2⁰ x 1) = 1833
With our entropy, each set of 11 bits can represent a number (the first set of 11 bits corresponds to the first number, the second set to the second number, and so on).
11011010010 = 1746
00010110010 = 178
11110010011 = 1939
10010000111 = 1159
11100001001 = 1801
01000000011 = 515
00001101001 = 105
10010100101 = 1189
11100111110 = 1854
01000010001 = 529
01011000010 = 706
1111111 = ?
You can see that there are enough numbers for 11 complete sets of 11 bits, corresponding to 11 words.
But what about the last (12th) set? There are 7 bits remaining, but you need 11 bits for a number. Where do the last 4 bits come from?
The Checksum
The final 4 bits of a seed phrase are known as the checksum. A checksum is a small piece of data added to detect errors within a dataset here, your seed phrase.
To get this checksum, you hash your entropy, producing a unique output.
What’s hashing? Hashing converts an input (like your entropy) into a shorter output (like a string of numbers or letters) using a specific algorithm called a hash function.
In BIP39 seed phrases, the hash function used is SHA-256. This function creates a sequence of hexadecimal characters (0-9, A-F)
from your entropy. You typically run this hash on a secure device, without internet or external connections, to ensure integrity.
For our example, hashing the entropy with SHA-256 produces:
ced25fa131e86640ffc9517b590f84877e40ad20f7f1ae88707ec79945d0d454
For a 12-word seed, convert the first hexadecimal character to a 4-bit binary number (for a 24-word seed, take the first two characters). These 4 bits, or checksum, are then added to the remaining 7 bits to make a final 11-bit number.
So, our checksum (1100) completes the leftover bits (1111111) to produce:
11111111100 = 2044
Completing the Seed Phrase
Now, with each 11-bit set representing a number, we can look up each in the BIP39 wordlist for its corresponding word. Since the wordlist starts at 1, add +1 to each number:
1746+1 = 1747 = surge
178+1 = 179 = bind
1939+1 = 1940 = venue
1159+1 = 1160 = movie
1801+1 = 1802 = thrive
515+1 = 516 = document
105+1 = 106 = artwork
1189+1 = 1190 = net
1854+1 = 1855 = treat
529+1 = 530 = drama
706+1 = 707 = flame
2044+1 = 2045 = zebra
Your 12-word seed phrase is:
surge bind venue movie thrive document artwork net treat drama flame zebra
Deriving Coin Accounts from Seed Phrases
A seed phrase is not enough to recover your coins.
You need know something called a "derivation path" which is a path taken to get from your seed phrase to your coins
Seed Phrase to Addresses
To understand this, let’s start with where your coins are actually “kept.”
Addresses
Coins are associated with addresses, which are long strings of letters and numbers provided by your wallet when you want to receive coins. An address might look something like this:
18L1EWSLwQfrUYDkY2cXG72wL4VVvcueE2
When someone sends coins to this address, those coins are now linked to it. But for wallet recovery, your wallet has to know the route from your seed phrase to this address.
So, how is an address created?
Public Key
Addresses are derived from a public key, which “locks” the coins to that address. A public key might look like:
020acf59763d9fd0dc8a23d49f94bc8f19c62a0e661b811c9b1b847a4e9ceedd13
But if coins are locked to a public key, how do you send them elsewhere?
Private Key
Coins associated with an address are “unlocked” by a private key, which works like a password to access those funds. The private key is unique and is used to “unlock” coins for transfer.
A private key might look like:
L3g7sAjcUGw6Dp9eJgEbq9zePaXC3DyRuUCruSyvqjGdk9e7bYSN
Each address has exactly one public key and one private key, forming a public/private key pair.
So how does your seed phrase lead to your addresses and their public/private keys?
To simply put, your seed phrase is put through a series of different functions in order to get to your addresses.
So let's start from the first step.
Seed Phrase to Seed
Your seed phrase is used as input in a function called Password Based Key Derivation Function 2 (PBKDF2), which outputs a number known as your seed.
To clarify, your seed phrase and seed are not the same.
A seed phrase is a 12-24 word series.
A seed is a long, complex number.
Seed phrases were created because copying down a long number accurately can be difficult. For example, a seed phrase like:
liberty bread eight solar income poet squirrel enlist wine educate profit define
when passed through PBKDF2, produces the following seed:
6bacd717a59732346c28a618ba6c2c4a8852f9f254ab838da1478a968f4061a73b9b0a5c6606a6d7ae37d5ea5a3dd118fef3532bf3b007b5d6aa94e5dc799446
Once we have this seed, we can use it in another function called HMAC-SHA512 (Hash-based Message Authentication Code, Secure Hashing Algorithm, 512-Bits). This function generates what’s called an extended key, another long string of letters and numbers.
From the seed above, the extended key would look like this:
xprv9s21ZrQH143K29vsCGbDCocAE1n1vrMQwn3jFqrFFeyY3wh7nXaxZNSkRgMXUMYBKHnu4BtPg4uDPro9Xbk8zRND54C2XRK4jxS5zBMo3eZ
The extended key can then be inputted into another function, along with a number between 0 and 4294967295
, to generate more extended keys. This branching system forms a family tree structure of keys, where each parent key generates children keys, which can each generate grandchildren keys, and so on.
The number used to create each child key is called an index, which uniquely identifies each child. This creates up to 4,294,967,296 keys
from each parent, producing an extensive branching structure.
All keys ultimately stem from the first extended key, known as the master extended key, designated as m. This is the root from which your derivation path begins.
Derivation Paths
Since your master key can branch out to 4,294,967,296 children keys, each of which can have another 4,294,967,296 children, navigating to your coins could get pretty overwhelming. So, to help your wallet “find” the right path, a sort of “map” is used, called the derivation path.
A derivation path specifies the indexes at each branching point, or level, to guide the wallet. It’s like following directions, where each step down the tree leads to the next branch or “level.” This path uses a specific format starting with m for the master key and is followed by six levels, separated by slashes:
m / Purpose' / Coin Type' / Account' / Change / Address
The apostrophe ('
) denotes hardened indexes, ranging from 2,147,483,648 to 4,294,967,295, while non-hardened indexes fall between 0 and 2,147,483,647.
Here’s what each level means:
Purpose
The “Purpose” level directs the derivation path along a specific route to reach the correct type of key. These paths are described in Bitcoin Improvement Proposals (BIPs), documentation that guides the features and workings of Bitcoin, including these derivation paths.
Some common paths are described in:
BIP 44
BIP 49
BIP 84
Each BIP’s designation number is used as the purpose index. For instance:
m / 44'
m / 49'
m / 84'
Each path defined by these BIPs takes you down a unique route with a specific functionality, as described in the proposal. Using m and one of these purpose indexes generates a new child key, taking us to the next level in the path.
Coin Type
Next is Coin Type, which specifies the type of cryptocurrency. Each coin type has a unique index number, for instance:
Bitcoin is 0'
Ethereum is 60'
Adding the coin type to the path gives us something like:
m / 44' / 0'
This index, combined with the purpose and master key, produces the coin-type specific extended key.
Account
This level designates the “account” for your coins, much like having separate bank accounts. You might store coins in “Account 0,” “Account 1,” and so on.
For example, if you want Account 8, you’d add it as the index, and the path now looks like:
m / 44' / 0' / 8'
This creates your “coin account” extended key.
Change
The Change index is usually either 0 or 1:
0 is used when receiving coins from others.
1 is used when receiving coins from yourself.
This change level helps differentiate between external and internal transactions. Let’s go over how these work in transactions next.
Transactions
When you send coins from one address to another, all the coins from that address are sent out.
If you’re receiving coins from someone else, the change index 0 is used along with your coin account extended key to produce the public/private key pair and address needed. This is the address you’ll share with others to receive funds.
If you’re sending coins to someone, change index 1 is used to generate a different key pair and address that will receive any remaining coins when you send less than the address balance.
All the coins across addresses in both change indexes contribute to your total balance.
So, for receiving coins, we’ll use index 0, and the derivation path now becomes:
m / 44' / 0' / 8' / 0
Address
Finally, at the last level, we use an address index (a number between 0 and 4,294,967,295) along with the current extended key to produce a specific private key.
From this private key, a public key is generated, which then creates an address. This allows you to create up to 4,294,967,296 addresses, each with a unique public/private key pair!
Keeping Track of Too Many Wallets
If you’ve created a new seed for each wallet, keeping track of them all can become difficult. You might be running low on hiding spots or simply tired of tracking what each wallet holds.
What if you could have just one seed and still use multiple wallets? You can with passphrases.
Using Passphrases
A passphrase is separate from your 12-24 word seed phrase. It’s an optional feature that lets you create a new wallet by adding an extra word or phrase to your seed. This feature is part of the BIP39 standard and is supported by many wallets.
A passphrase can be almost any character (A-Z, a-z, 0-9, special characters). Each unique passphrase added to your seed generates a new wallet:
In other words:
Seed 1 = Wallet A
Seed 1 + Passphrase 1 = Wallet B
Seed 1 + Passphrase 2 = Wallet C
Seed 1 + Passphrase 3 = Wallet D
This way, a single seed can support multiple, distinct wallets, each tied to its unique passphrase.
Passphrases also add security against physical theft. If someone finds your seed, they can’t access your coins without the correct passphrase. Plus, using only the seed without a passphrase might lead them to believe they’ve found everything.
With multiple seeds, finding one could put some assets at risk. But with a single seed and multiple passphrases, your assets are safer since they’d also need the passphrases.