Safety deposit boxes opened with keys

Make Your Private Seed Words Unhackable

By Michael_Brown | Wallet Security | 2 Mar 2020


As I'm new to crypto, and being safety conscious, I bought a hardware wallet to keep my precious coins safe from would-be hackers of centralised exchanges. Without access to my private keys, hackers cannot gain access to the millions your hardware wallets hold. Haha, my coins are safe!

But wait, what if something happens to my wallet (theft, hardware error, lightning strikes my house and causes a fire, etc.)

Lightening striking trees. Photo by Max LaRochelle on Unsplash

Those events could potentially cost me a fortune (I know, optimistic thinking). People smarter than I have already thought about this and their solution was to create a mnemonic seed, which is a list of random words that represent the private keys of the hardware wallet. With this mnemonic seed, even if something happens to my wallet, I can still access the funds associated with that wallet.

Phew, if anything happens, I just have to use the mnemonic seed words that I wrote down, and voila, I'm back in action. But wait, now I have a new problem, as if someone gains access to my mnemonic seed words, they could access my funds and transfer them to whatever address they like. Also, if something happens to my tiny scrap of paper on which I wrote my seed words, (flood, fire, etc.) then I've lost my seed words forever.

Damn, now I have two problems.

If like me, this bothers you, then I can share a quick and straightforward method to encrypt your mnemonic seed words using unbreakable encryption that only requires a pen, paper, and a die (two dice will make it quicker)! Even if would-be hackers/thieves were able to find your encrypted seed words, they would never be able to decipher it without the key.

I'll explain the theory behind this easy encryption, and share with you a python program that you can copy to encrypt your personal seed words and guarantee their protection.

Man's hand with three dice hovering above it.  Photo by El Pepe on Unsplash

One Time Pad

Let's say you want to encrypt the word 'HELLO'. To do so, you only need first generate a list of random numbers at least as long as the message you want to encrypt. This will be your secret key. So for this example, we have five letters so need five random numbers from a range of 1 - 26.

Now, when you bought that twenty-six sided die at a car boot sale decades ago, little did you know how handy it would be! What, you don't own a twenty-six sided die to generate the random numbers. Don't worry, neither do I, so just use one or two regular die/dice and the table below:

Six by six grid, showing a total of thirty-six numbers.

How it works is simple, roll one die for the column number, and one for the row number. If the number you land on is twenty-six or less, write it down. If it is higher than twenty-six, roll again. Keep going until you have the required number of random digits.

So if you rolled a 2, then a 4, you would find the second row and the fourth column, i.e. '10', and write this down as your first random number. If you then rolled a six and another six, you would not write anything down and roll again. Let's pretend we did this for a total of ten times and our random numbers are:

10, 16, 26, 17, 1

At this point, the hard work is over and you are one step away from perfect secrecy. 

All that remains is for you to take each letter of the message you want to encrypt and shift it by each random number. Starting with the letter 'H', we move ten letters ahead in the alphabet and arrive at the letter 'R'.

Alphabet letters, with 'H' highlighted and a shift of ten made, with 'R' highlighted.

  • 'E' is shifted by 16 to 'U'
  • 'L' is shifted by 26 to 'L'
  • 'L' is shifted by 17 to 'C'
  • 'O' is shifted by 1 to 'P'

Notice that any shift that goes further than 'Z' simply loops back around to 'A' and continues from there.

Original message: 'HELLO'

Encrypted message: 'RULCP'

The encrypted message above has two powerful properties:

    1. The shifts never fall into a repetitive pattern, because we have a list of random numbers at least as long as the message we are encrypting.
    2. The encrypted message will have a uniform frequency distribution, resulting in no frequency differential.

With the above points in mind, there is no information leak caused by repetition in the encrypted message and it is truly unhackable!

Exceptions

There are none. Seriously, Claude Shannon proved, using information theory considerations, that the one-time pad has a property he termed perfect secrecy; that is, the encrypted message gives absolutely no additional information about the message, apart from the total length. This is because, given a truly random key that is used only once, a ciphertext can be translated into any plaintext of the same length, and all are equally likely.

To give you a feel for the math, let's say a hacker steals your encrypted message 'RULCP'. All that they know is you have a message which is five letters long. Okay, what if they tried a brute force attack to determine the key?

Well, the first letter could have twenty-six shifts, the second twenty-six as well, etc. So:

26 x 26 x 26 x 26 x 26 = 26^5 = 11, 881, 376

There are nearly 12 million possible combinations of secret keys. If the hacker had an amount of time, they would eventually stumble upon the key "10, 16, 26, 17, 1" that produces "HELLO". However, they would also find that "6, 20, 18, 24, 24" produce "LATER", an equally plausible message. In fact, we could make any five-letter word we choose by altering the secret key.

That alone is enough to guarantee your encryption, but it gets better; if you have twenty words with a total of 100 letters, that means the total number of possible combinations are:

26^100 = 3142930641582938830174357788501626427282669988762475256374173175398995908420104023465432599069702289330964075081611719197835869803511992549376

It is estimated that there are between 10^78 to 10^82 atoms in the known, observable universe. There are far more possible combinations available than atoms in the universe; brute force isn't an option. Even if it were, there is no way to know the number of seed words contained in the encrypted message, and the length of each seed word. The only way to proceed would be to guess every single combination of words possible that equal a length of one-hundred letters.

Decryption

Decryption is only possible if you have the secret-key. All you have to do is the reverse of encryption, which in this case means subtracting the shift from the encrypted letters i.e. 'R' minus 10 is the letter 'H', etc.

Perfect Secrecy

You've now encrypted your seed words, and at this point, you can destroy the note containing the unencrypted seed words. If the worst were to happen to your hardware wallet, you could easily decrypt your encrypted seed words and recreate your wallet with all your funds available.

For someone to decrypt your encrypted message, they would now need access to both your encrypted message and your secret-key. Not only is that unlikely to happen, but there are also far easier targets to pick than paranoid - I mean, safety-conscious - people like us, so would-be thieves are far more likely to target the low hanging fruit and leave us alone.

However, do not get complacent, as for this encryption to remain unhackable, you need to ensure that you store your secret key and encrypted message in separate locations. If they are found by anyone, by themselves they have no value whatsoever; together, they are able to access your hardware wallet.

If either piece of information is compromised, decrypt your seed words, encrypt them using a new secret-key, and destroy the old encryption/secret-key. 

The beauty of this encryption is that you can now make a back up of the encrypted message and secret-key and store them in two other separate locations. Now you have insurance should anything happen to the originals and they are still of no value to anyone else but you.

Don't Believe Me

If at this point you still have any lingering doubts, allow me to assuage them with a little example. Below you will find an encrypted message, I will give the first person to decrypt it 10 BAT.

SAETYYGAFCQBADGNQBRDXQRWESXDZDPODDXLPLDC

Leave your answer as a comment and if you are correct I'll let you know and transfer the BAT to an address of your choosing.

Python

I've put the python script below that will allow you to quickly encrypt and decrypt your seed words. The only thing you have to do is generate random numbers with a pair of dice at least as long as your message (don't use a computer to generate random numbers as you want truly random numbers).

After doing this, you can sleep a little easier at night knowing should the worst happen to your wallet, you are prepared for it and have access to unhackable backups of your seed words.

*Disclaimer: The advice given here should be followed at your own risk and I cannot accept any responsibility for actions taken by you. If you destroy your seed words and then lose either your secret-key or encrypted message, your seed words are gone forever. Encrypting your seed words adds an unpenetrable layer of security, and if done correctly, will ensure that your secret keywords remain just that, secret.

 

# Generate a dictionary with alphabet letters as the keys, letter positions as the values.
ALPHABET = {chr(65 + i): i for i in range(26)}
# Generate a dictionary with letter positions as the key, and alphabet letters as the values.
LOCATION = {i: chr(65 + i) for i in range(26)}

# Message to encrypt
MESSAGE = 'HELLO'

# Random numbers to shift by
SHIFTS = [10, 16, 26, 17, 1]

# Create empty string to hold encrypted message
ENCRYPTED_MESSAGE = ''

# loop through each letter in the message we want to encrypt
for i in range(len(MESSAGE)):
# Get letter to encrypt
letter_to_encrypt = MESSAGE[i]
# Find the letter's numerical position in alphabet
start = ALPHABET[letter_to_encrypt]
# Add the shift to this position, and use modulo 26 to loop around if we exceed 26
shift = (start + SHIFTS[i]) % 26
# Get the encrypted letter
encrypted_letter = LOCATION[shift]
# Append the encrypted letter to ENCRYPTED_MESSAGE
ENCRYPTED_MESSAGE = ENCRYPTED_MESSAGE + encrypted_letter

print(ENCRYPTED_MESSAGE)

DECRYPTED_MESSAGE = ''
# Decrypt the message
for i in range(len(ENCRYPTED_MESSAGE)):
# Get the letter to decrypt
letter_to_decrypt = ENCRYPTED_MESSAGE[i]
# Find the letter's numerical position in alphabet
start = ALPHABET[letter_to_decrypt]
# Subtract the shift from this position, and use modulo 26 to loop around if we exceed 26
shift = start - SHIFTS[i]
# if shift is negative, loop it back from 26
if shift < 0:
shift = 26 - abs(shift)
# Get the decrypted letter
decrypted_letter = LOCATION[shift]
# Append the encrypted letter to ENCRYPTED_MESSAGE
DECRYPTED_MESSAGE = DECRYPTED_MESSAGE + decrypted_letter

print(DECRYPTED_MESSAGE)

How do you rate this article?

48


Michael_Brown
Michael_Brown

Physics graduate, with a passion for programming in Python.


Wallet Security
Wallet Security

A guide to ensuring your coins remain your coins.

Send a $0.01 microtip in crypto to the author, and earn yourself as you read!

20% to author / 80% to me.
We pay the tips from our rewards pool.