Crypto Security How-tos

Generating a Seed Phrase using a Calculator.

If you prefer to take a few extra steps to generate your 12-word seed phrase using a calculator to ensure randomness, this article is for you.

Using an offline calculator to generate a BIP39 seed phrase is one way to establish a very high level of confidence in the randomness and initial security of seed phrases - especially compared to the default wallet approach.

When choosing a method to generate seed phrases you have to ask yourself these questions: Do you trust that the device you are using is absolutely free from any malware? What is secure today is not always secure tomorrow. Furthermore, do you trust that the developers created a sufficiently random RNG? One simple math mistake can potentially lead to all generated private keys being predictable and therefore vulnerable to brute force attack. Even if you trust both, you can never be 100% certain.

Using a calculator or dice to generate your seed phrase removes all of these concerns by providing a true air-gapped environment to generate entropy. By taking the process offline, you can be certain that the resulting entropy is free from corruption. The calculator and dice methods both offer you the peace of mind that comes from controlling the entropy generation yourself, and the added confidence that comes from generating the seed phrase entirely offline, reducing the risk of compromise by interception.


How do calculators generate randomness?

Calculators can rely on various mechanisms for producing randomness, depending on their design - their entropy source can be derived from things like microseconds since being powered on, chip-related heat levels, or other variable conditions. The calculator's Random function can mathematically transform these unpredictable base values into pseudo-random numbers.

To ensure maximum unpredictability, if a calculator is used as a random number generator, it should not be used in an "out-of-the-box" state, but should first be initialized to a non-generic state by being powered on and off several times and used to perform some routine calculations before performing random seed calculation.

Moreover, it is useful to introduce an additional source of entropy, implementing the method used in all electronic slot machines in casinos: they program a random number generator to create numbers constantly, and then you pick blindly, at will, with a button push. It is easy to do the same using a programmable calculator. If your scientific calculator doesn't support programs, then you can achieve the same effect manually with some additional manipulations.

Preparation for seed phrase generation with a calculator.

To prepare for seed phrase calculation using a calculator, be ready with:

1. A standalone scientific calculator with a Random function.

Calculator models that support the Random function include the Hewlett Packard 10S or 30S, Texas Instruments TI-30XB or TI-83/84, Casio FX-991 or FX-5800P, or Sharp EL-W535.

2. A BIP39 word list (for English, see https://github.com/bitcoin/bips/blob/master/bip-0039/english.txt).
3. Your cryptocurrency wallet, ready to be initialized with the seed phrase you are generating.
4. Scratch paper on which to write the generated random numbers and matching words sequentially.
5. An understanding of how to calculate and verify the last word of the seed phrase. (More details below.)
6. A strategy and equipment for backing up the seed phrase after it is generated. (For example, the seed phrase could be stored in a crypto wallet, and punched onto a steel card.)
7. A plan for how to dispose of the scratch paper once the seed phrase has been stored and backed up. (For example, the scratch paper, and the few pages beneath it in the pad, which may contain pressure marks, may be burned in a fire-safe container.)

The calculator's Random function.

Most calculators allow the user to set an integer range for randomization that is inclusive of starting and ending numbers (for example, from 1 to 2048). The exact key(s) to call the Random function on any specific calculator will be defined in the user manual, but the function is likely called using the button labeled "Rand," or a combined keypress of Shift-Rand or 2nd-Function-Rand.

On programmable calculators, it is called with randInt(A, B) function, where A and B are the inclusive starting and ending numbers. Test the operation of the Random function by setting the randomized range as 1-3, and then check the results of a few runs to confirm that the initial and ending numbers specified are included in the result set. Then set the randomization range to 1-2048, to allow mapping results to the BIP39 word list.

The high-level view of seed phrase generation with a calculator.

Generation of most of the seed phrase words is straightforward: using the calculator's Random function, execute and write down the number and the corresponding word from the BIP39 word list onto paper in the order of their generation, repeating until 12 numbers and words have been created.

The last word of the seed phrase requires extra analysis and often adjustment because the BIP39 standard requires that for phrase integrity purposes, the last word contains a valid checksum derived from the first eleven words. Only one word out of each 16-word block in the wordlist will include a valid checksum for the first 11 words selected.

The next steps describe how to generate the words, and how to identify the correct last word. Below, we demonstrate two approaches, for both a programmable and a non-programmable calculator.

1. Generating a random seed phrase using a non-programmable calculator.

If you are using a non-programmable calculator, then the generation of most of the seed phrase words is straightforward.

  1. Using the calculator's Random function, execute it with the range of (111111, 999999) several times to warm up until you get several numbers without zeros at all. Pick two of them and use its digits as twelve different values in seconds for random countdown timers in Step 4.
  2. Then set a phone timer (not a countdown), start it, and put it in front of you for your convenience.
  3. Execute calculator's Random function with the range of (1, 2048).
  4. Keep hitting [enter] to execute the same Random function over and over for X seconds, where X is the first digit of the first six-digit random number generated at Step 1.
    The precision of timing does not affect the results, these steps introduce external random factors, as if we are shaking the dice before throwing.
  5. Once complete, write down the number and the corresponding word from the BIP39 word list onto paper in the order of their generation.
  6. Repeat Steps 4 and 5 until 12 numbers and words have been created.


The Last Word of the seed phrase requires extra analysis and often an adjustment because the BIP39 standard requires that for phrase integrity purposes, the last word contains a valid checksum derived from the first eleven words. Only one word out of each 16-word block in the wordlist will include a valid checksum for the first 11 words selected. See Identifying the Last Word, for the steps.

2. Generating a random seed phrase using a programmable calculator.

If you have a programmable calculator then you can follow a more automated approach:

The provided example is for TI-83/84 calculators.

To create a program navigate using arrows and the following buttons:
[prgm] -> New -> 1: Create New -> name=RANDOM -> [enter]
and then put the following code into editor:

PROGRAM:RANDOM
:While 1
:randInt(1,2048)→R
:If getKey>0
:Disp R
:End
  • Operations While, If, End can be accessed in program editor in [prgm] -> CTL folder
  • Operation randInt( can be accessed in program editor in [math] -> PROB folder
  • Operation can be accessed in program editor in [sto→]
  • Operations getKey, Disp can be accessed in program editor in [prgm] -> I/O folder
  • Operation > can be accessed in program editor in [2nd] -> [math] -> TEST folder

After finishing code you can start the program by navigating to [alpha]->[graph][f5]-> 1: Execute Program [ENTER]

Press ANY KEY except ON to get the next number generated. You can warm up the generator with multiple test generations and check if it works correctly, displaying random numbers within a range of 1 to 2048.

Now you are ready to start generation: press ANY KEY again and write down the number and the corresponding word from the BIP39 word list onto paper in the order of their generation, repeating until 12 numbers and words have been created.
When you press [ON]->[ENTER], the program is interrupted and stops running.

The last word of the phrase requires extra analysis and often adjustment because the BIP39 standard requires that for phrase integrity purposes, the last word contains a valid checksum derived from the first eleven words. Only one word out of each 16-word block in the wordlist will include a valid checksum for the first 11 words selected. Proceed to the next step Identifying the Last Word.

Notes:
The program is running all the time, generating around 30 numbers per second, using randInt(1,2048). Which of the numbers is displayed depends on the moment when you press a key.

This method is used in all electronic slot machines in casinos. Their pseudo-random number generators create around 500 numbers per second, it is needed because the selection is many times smaller than 2048.

Identifying the Last Word.

There are two ways to identify the valid last word:

1. While not connected to the internet, and in a secure operating environment, run the script provided at the end of this article in the code debugger window of a browser. Before running the script, modify the script line containing the array named "data" so that it holds the twelve integers that were randomly selected with your calculator. For example, the line below from the script would indicate that you calculated the following twelve numbers on your calculator:

data = [101, 502, 962, 1400, 1607, 1817, 1090, 1827, 820, 1334, 156, 1073]

which would map to the following words:

arrive dirt join puzzle silver toast market tone grid pluck beach maid

To run the script in the Firefox browser, open the Web Console (shortcut: Control-Shift-K), and at the prompt, paste the entire script, then press Enter. After the script runs, it should show you what the valid twelfth-word seed number from that block of 16 words should be (rather than the number that you generated with the calculator). The output of the script should look something like this:

function checksum12words(date {
if (data.length !=12) return console.log("ERROR: Need 12 words numbers as input")
let binder = (s, 1 = 8) => s.toString(2).padstart(1,"0")
let tone = (bytes) => bytes.map( x => x.toString(16).padstart(2,0) ).join(' ')
let bytes = data.map( x => binder(x - 1, 11)) //convert 0-index to binary_
Entropy is : 0c87d5e0d77c8dc6220f226674d44dc3
"OK" Your 12th word index is: 1078

This script output would reveal that the twelfth number in your seed phrase, adjusted to have a valid checksum, should be 1078, rather than the 1073 originally chosen with the calculator. Correspondingly, the BIP39 word list shows that the valid last word of your seed phrase should not be "maid," but instead, "mammal."

2. The second method of identifying a valid last seed phrase word can be done instead of or in addition to the first method. It includes the use of an offline mnemonic converter tool. This involves typing or pasting the original 12 seed phrase words into the converter tool, then using trial and error to determine which word of the 16-word block containing the originally-chosen 12th word contains a valid checksum relative to the phrase. For example, if the calculated 12th word number was 1073, first identify which word block contains the number 1073: in the BIP39 wordlist of 1-2048 words, the 68th 16-word block contains words 1073-1088. Thus, the word block that contains word 1073 is 1073-1088.

Tip: Some people highlight every 16th word in a printed wordlist to make block identification easier.

Now that we know that the valid 12th word is in the 1073-1088 range of the word list, paste the original set of words generated by the calculator choices into the "BIP39 Mnemonic" field of the mnemonic code converter tool:

arrive dirt join puzzle silver toast market tone grid pluck beach maid

The tool will automatically calculate and will show the error "Invalid mnemonic," because its calculation with the last word "maid" does not yield a valid checksum.

Now begin the trial and error testing, changing the last word in the phrase from "maid" (word 1073) to "mail" (1074), "main" (1075), "major" (1076), and "make" (1077). Each time, the tool again shows the "Invalid mnemonic" error. But when we change the last word to "mammal" (1078), the error goes away, and the converter tool is satisfied. (And this result matches what we found in methodology #1 above.) The seed phrase has been successfully created!

Along with your now-valid BIP39 seed phrase, the converter tool output also shows various other information, like addresses, QR codes, extended keys suitable for use in BIP44 wallets, and more. However, you are about to input your seed phrase into your own wallet, and once you do, you should rely on your own wallet for the other information (which it will generate from the seed phrase).

Cleaning up the environment after generating a seed phrase.

After the seed phrase information is safely stored, the browser cache should be cleared, and the browser process exited, to remove all traces of sensitive data from the browser and computer memory.

If you used a temporary operating environment such as Tails Linux, then clearing browser memory is not strictly necessary, since nothing from the entire operating environment is written to disk, and everything is removed from memory when the instance is stopped.

If you used a browser in an offline, non-temporary operating system, documentation for the specific browser version used should be consulted to ensure completion of all steps needed to clear the cache and history for both the rendered window and the console used to run the script.

For Chrome, this may include choosing the menu item "More Tools," "Clear Browsing Data," "All Time," and additionally selecting "Cookies and Site Data," "Cached Images and Files," and then clicking "Clear Data."

To clear console history in Chrome, the console window offers a context menu to "Clear Console History."

For Firefox, this may include choosing the menu item "Privacy and Security," "Cookies and Site Data," checking all available boxes, and then clicking the "Clear" button.

To clear console history in Firefox, run the "clearhistory()" command.

Security Tip: Be very careful with seed words in browsers

The steps in this article are provided to help the reader understand a methodology that could be used to generate a 12-word seed phrase (aka "mnemonic phrase") using an offline calculator as the source of randomness. Some of the later steps, however, include running a script in a computer browser. Mnemonic phrases should be generated only in a secure environment, to minimize risks of interception, tampering, or theft. Mnemonic phrases should never be transmitted over any network, or stored on any computer, without the protection of being encrypted.

To ensure a secure operating environment for the seed phrase generation steps that are performed in a browser, a good option is to use a browser inside of an offline, temporary operating system such as Tails Linux. When copying the seed words generated in the browser into long-term secure storage, do not leave an electronic trail behind by copying and pasting them into files on interim storage devices ... be ready with your wallet at the time that you generate the words, and then enter them into your wallet.

Checksum script code below:

function checksum12words(data) {
if (data.length != 12) return console.log("ERROR: Need 12 words numbers as input")
let binstr = (s,l =8) => s.toString(2).padStart(l,'0')
let tohex = (bytes) => bytes.map( x => x.toString(16).padStart(2,0) ).join('')
let bytes = data.map( x => binstr(x - 1, 11)) // convert 0-index to binary
.join('').match(/.{1,8}/g) // split 8 bits
.map( x => parseInt(x, 2)) // convert to UInt8
if (bytes.length != 17) return console.log("ERROR: Something is wrong, check your input")
bytes.pop() // remove wrong 17th byte of checksum
console.log("Entropy is :",tohex(bytes))
window.crypto.subtle.digest("SHA-256", new Uint8Array(bytes).buffer).then( x => {
if (x.byteLength != 32) return console.log("ERROR: Wrong SHA256")
let hash = new Uint8Array(x)
let cs = binstr(hash[0]).match(/.{1,4}/g)[0]// Thats our checksum
// Take byte 15 for full 11 bits of our final word
let bits = [binstr(bytes[15]),cs].join('')
if (bits.length != 12) return console.log("ERROR: Wrong final word bits")
//console.log(bits)
console.log("Your 12th word index is: " + (1+parseInt(bits.substr(1),2)))
})
return "OK"
}
data = [101, 502, 962, 1400, 1607, 1817, 1090, 1827, 820, 1334, 156, 1073]
checksum12words(data)
Crypto Security How-tos

Generating a Seed Phrase using a Calculator.

If you prefer to take a few extra steps to generate your 12-word seed phrase using a calculator to ensure randomness, this article is for you.