Databases, ciphers and secrets: a guide to securely storing private keys from Cake Wallet


11/30/2021 ForkLog

#private keys#encryption

Almost any cryptocurrency wallet allows you to make a backup - save the private key in a special file to restore access if the device is lost or damaged. But this creates new problems: the file can be stolen by attackers.

The developers of the Cake Wallet crypto wallet talk about open source software for securely storing and encrypting private keys.

We break a wallet in three minutes

Desktop, mobile and browser wallets store private keys on the user's device. For example, the Exodus crypto wallet places them in the AppRoaming folder on Windows and in Application Support on macOS.

The most important things about them are the seed.seco and passphrase.json files. The first contains the private key, and the second contains the phrase for decrypting it.


Contents of the exodus.wallet folder in Application Support. To access it you need to enable the display of hidden folders.

If a hacker copies the files to his computer, he will gain access to the wallet. We did the same in the example below.


Transfer files to another computer. Bitcoin addresses match.

This does not mean that Exodus and other desktop wallets are unreliable. We specifically did not use passwords, encryption, or 2FA to show the theft mechanism.

Most wallets offer to encrypt key files with a password. But even in this case, they will remain in an obvious place and will be vulnerable to a brute force attack.

Stealing files from a smartphone is more difficult: iOS and Android do not provide full access to the file system. We installed Cake Wallet, MyEtherWallet and TON Surf wallets on our smartphone, but could not find folders with keys without root access.

However, the phone can be lost or broken, and thus lose the cryptocurrency. In this case, it is worth making a backup of your wallet: saving the private key or mnemonic phrase on a separate device, and then encrypting them.

In addition, backups allow you to safely use desktop wallets. To do this, you need to turn them into non-custodial ones: manually import the private key each time, and clean the folders when finished.

What is the private key for?


Sending cryptocurrency transactions
The private key performs two main functions. The first is the secure storage of cryptocurrency, since only those who know the private key of Bitcoin can conduct transactions with these assets. That is why you need to be extremely careful when creating it, and under no circumstances show it to third parties, and also not store it on the Internet, and ideally even on computers that are connected to the Internet.

The second function is transaction signing. The private key is also a digital signature. As mentioned above, each private key has a unique public key or address associated with it. When sending a transaction to the network, nodes check the correspondence of the sender's address with its private key, while information about the latter remains secret to everyone, even validators. Once the required number of confirmations are received, the transaction will be delivered to the recipient.

How to make a backup correctly

To access the wallet you need a private key or a seed phrase - you can save one or the other.

It is better to choose a seed phrase. It consists of English words, which means there is less chance of making a mistake when creating a backup.

Seed phrases and private keys are approximately equally resistant to brute force - a hacking method by trying possible combinations.

Data can be secured in four ways:

  • write to password manager;
  • save to a file and encrypt it;
  • upload to encrypted cloud storage;
  • break into pieces using Shamir's secret.

We will show them using open source tools as an example: KeePassXC, PGPTool, Cryptomator and ASecuritysite.

Remember that there is no absolutely secure way to store keys. But it will take months to hack a protected wallet, and a few minutes to hack an unprotected one.

How to properly store private keys


Storing private keys
It is important not only to create a reliable key, but also to store it correctly. In general, there are three storage options: on paper (metal), on electronic media, in memory. However, no matter which method you choose, it is important to remember that only you should have access to the private key.

Now let’s tell you what options there are for storing a Bitcoin private key:

  • On paper or metal. This method is most relevant for paper wallets, but this way you can store a private key created by any method - you just need to rewrite it. However, such storage is not safe: you may lose the sheet, it may burn or get wet. For greater strength, it can be laminated or made from metal;
  • On a flash drive. This is one of the most reliable methods. You need to use a separate flash drive (preferably new and checked for viruses) and perform all operations offline. There are several storage options: as a text document, a screenshot, or an original file in wallet.dat format. You also need to put a password on the flash drive;
  • On the computer. This is also a fairly reliable storage option if the device is not connected to the Internet and is working properly. Otherwise, he may either become a victim of attackers, or “fly”. It is also recommended to set a strong password on the file itself and on the computer;
  • In mind. This is perhaps the safest way. However, it will only work if you used a mnemonic phrase. Because remembering a set of random numbers and letters is simply unrealistic.

Password manager KeePassXC

A password manager is an application for storing a large number of key-value pairs. Essentially, it is an encrypted database that can only be opened with a master key.

We'll demonstrate how a password manager works using KeePassXC, a free and open-source application for Windows, Linux, and macOS.

When you launch it for the first time, KeePassXC will prompt you to create a database. Enter its name in the Database Name .


The description field can be left blank. You will only see it in settings.

In the second step, configure the time it will take for each attempt to select a master key ( Decryption Time ). The default value is 1 second, the recommended value is 5 seconds.


The ideal decryption time is five seconds. In this case, the hacker will check 20-30 passwords per minute.

Then enter and confirm the master key. It must be unique - do not use existing or similar passwords. Please note that KeePassXC supports characters like ©, ✓ or ⌀, which are not found in standard keyboard layouts and brute force dictionaries.

After this, give the database file a name and select a location where to save it.


Choose a folder or device where you will definitely not lose the database file.

To create a backup, click the plus sign on the top toolbar. Give the entry a name, for example seed phrase. If you don't want to leave a hint for hackers, leave the field blank.

Enter your seed phrase or private key in any field and click OK . We recommend using the Password : KeePassXC hides its contents when browsing the database.


The Title, Username, URL and Notes fields can be left empty. They help you navigate the contents of the database.

To copy a key or seed phrase, right-click on the entry and select Copy Password from the drop-down list.


KeePassXC hides the password length, so instead of symbols, the Password field displays dots.

The database should be copied to a flash drive or uploaded to the cloud in case the hard drive fails.

What does a Bitcoin private key look like?

Let's look at the example of Bitcoin to see what a private key looks like. Bitcoin is based on the SHA-256 cryptocurrency algorithm, which creates a 256-bit number consisting of zero and one.

However, using such a long dial is very inconvenient and, moreover, the key must be encrypted. Therefore, the private key for a Bitcoin account is created as a 32-byte number, which consists of 64 characters. For each character there are two values ​​(zero or one) from the above 256-bit number. Numbers from 1 to 9 and alphabetic characters from A to F are used.

☝️

Example of a Bitcoin private key: B4653223363AA61F20BD08FC233AC37262

It is almost impossible to guess or select it using the “brute force” method. It is essentially a number in the range from 1 to 10 to the 77th power. If we imagine that a person has the ability to sort through one trillion numbers per second, then finding one private key would take at least a million ages of the existence of planet Earth.

But some researchers believe that with the development and improvement of quantum technologies, there will be ways to hack the blockchain.

It is also worth saying that with the development of the cryptosphere, different formats for storing Bitcoin private keys have appeared. These are alternative formats called the "Wallet Import Format". There are three of them:

  1. Hex: 1E99674A4CA27608A45A1813ABB0E9E52CFA330AC563EDBB32C8AAC6A964AECA.
  2. WIF: 5J3nBbAG58CuQ346RNLpPUA
  3. WIF-compressed: KxFC1jnghCoACiATWZ3oXa748VN6ac3TYzGkd7YbsqGLY

These formats store the same key. Each format can be easily converted to any other.

Encryptor PGPTool

PGP (Pretty Good Privacy) is the name of a library of functions for encrypting data and applications based on it.

PGP encryption allows you to protect the contents of emails, hard drives and individual files. PGP applications work like crypto wallets: they encrypt information with public keys and decrypt it with private ones.

We will make a backup of the text file with the seed phrase using PGPTool, an open-source desktop PGP client. To run you will need any operating system that supports the Java Runtime Environment.

Write the private key or seed phrase into a text file and save it on your computer. Install and run PGPTool.

Click the Key ring to create a new pair of public and private keys.

PGP is used to encrypt emails, so many applications ask you to enter your name, password and email. It is not necessary to indicate real data: in our case, this is the name of the key pair.

After filling out the basic information, set a password and click the Create .


If you don't want to provide your real email address, enter any combination of letters from @gmail.com.

Create a backup: click on the Encrypt File and select the file with the seed phrase.

Use same folder checkbox and specify a save location. Otherwise, PGPTool will place the backup in the folder with the original file.

Click the Encrypt .


If you enable the Delete source file checkbox, the client will delete the source file after encryption.

When encryption is complete, PGPTool will display the message “File was encrypted successfully.” The backup is ready. Make a copy of this file in case your main device is lost or damaged.

To decrypt the backup and read the seed phrase, click the Decrypt file and select the encrypted file. Enter the password you specified when creating the key pair.


The Key field displays your name and email address, not the key itself.

Select a folder to save the decrypted file and click the Decrypt .


Be sure to save the PGP key to an external drive so as not to lose your wallet if your hard drive is damaged.

Click the Key ring , right-click on the key and select Export private key from the drop-down list. Specify the folder to store the file with the key and click the Save .


The PGP client will save the key in an asc file.

Remove key from the list . If a hacker does gain access to the computer, he will not be able to decrypt the file.

How to Generate Your Own Bitcoin Key

Original author: Timur Badretdinov.

In Cryptootogurns, the private key allows the user to access their wallet. The person who holds the private key has complete control of the coins in that wallet. For this reason, you must keep it secret. And if you really want to generate the key yourself, it makes sense to generate it securely.

Here I will provide an introduction to private keys and show you how you can create your own key using various cryptographic functions. I will provide a description of the algorithm and code in Python.

Do I need to create a private key?

Most of the time you don't. For example, if you use a web wallet like Coinbase or Blockchain.info, they create and manage the private key for you. It's the same for exchanges.

Mobile and desktop wallets will usually also generate a private key for you, although they may have the ability to generate a wallet from their own key.

So why create it anyway? Here are the reasons I have:

  • You want to make sure no one knows the key
  • You just want to learn more about cryptography and random number generation (RNG)

What exactly is a private key?

Technically, the private key for Bitcoin (and many other cryptocurrencies) is a series of 32 bytes. Now there are many ways to write these bytes. This could be a string of 256 and zeros (32*) or 100 rolls for dice. It can be a binary string, Base64, A WiF Key, Mnonic phrase or finally a hex string. For our purposes, we will use a hex string that is 64 characters long.

Why exactly 32 bytes? Great question! You see, to create a public key to a private one, Bitcoin uses ECDSA , or the Elliptic Curve Digital Signature Algorithm. More specifically, it uses one specific curve called secp256k1 Failure

Now this curve is of order 256 bits, takes 256 bits as input and outputs 256 bit integers. And 256 bits are exactly 32 bytes. So, to put it in another way, we need 32 bytes of data to feed this curve algorithm.

There is an additional requirement for the private key. Since we are using ECDSA, the key must be positive and must be less than the order of the curve. The order ecp256k1 is FFFFFFFFFFFFFFFFFFFFFFFFFFEBAEEDCE6AF48A03BBFD25E8CD0364141 , which is quite large: almost any 32-byte number will be smaller than it.

Naive method

So how do we create a 32 byte integer? The first thing that comes to mind is to simply use the RNG library in your language of choice. Python even provides a nice way to generate just enough bits:

import random bits = random.getrandbits(256) # 30848827712021293731208415302456569301499384654877289245795786476741155372082 bits_hex = hex(bits) # 0x4433d156e8c5 3bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c32 private_key = bits_hex[2:] # 4433d156e8c53bf5b50af07aa95a29436f29a94e0ccc5d58df8e57bdc8583c 32

It looks good, but in reality it is not. You see, regular RNG libraries are not designed for cryptography as they are not very secure. They generate numbers based on seeds, and by default the seed is an exact time. So if you know roughly when I generated the bits above, all you have to do is brute force a few options.

When you generate a private key, you want to be extremely secure. Remember that if someone finds out the private key, they can easily steal all the coins from the corresponding wallet, and you have no chance of ever getting them back.

So let's try to make it safer.

Cryptographically strong RNG.

Along with the standard RNG method, programming languages ​​usually provide RNGs specifically designed for cryptographic operations. This method is generally much more secure because it draws the entropy directly from the operating system. The resulting RNG is much more difficult to reproduce. You can't do this knowing the generation time or having the seeds, because there are no seeds. Well, at least the user is not part of the seed - rather, it is created by the program.

In Python, cryptographically strong RNG is implemented in the Secrets module. Let's change the code above to force the confidential key generation to be secure!

import secrets bits = secrets.randbits(256) # 46518555179467323509970270980993648640987722172281263586388328188640792550961 bits_hex = hex(bits) # 0x66d891b5ed7f 51e5044be6a7ebe4e2eae32b960f5aa0883f7cc0ce4fd6921e31 private_key = bits_hex[2:] # 66d891b5ed7f51e5044be6a7ebe4e2eae32b960f5aa0883f7cc0ce4fd6921e31

It is amazing. I bet you won't be able to reproduce this even with access to your PC. But can we go deeper?

Specialized sites

There are websites that generate random numbers for you. We'll look at just two here. One of them is Random.org, a well-known general purpose random number generator. Another one is Bitaddress.org, which is designed specifically for generating Bitcoin master key.

Can Random.org Help us generate a key? Definitely how they have a Service to generate random bytes. But there are two problems here. Random.org Claims to be a truly random generator, but can you trust it? Can you be sure that this is truly random? Can you be sure that the owner is not recording all generational results, especially those that look like private keys? The answer is up to you. Oh, and you can't run it locally, which is an additional problem. This method is not 100% secure.

Now Bitaddress.org is a completely different story. It's open source, so you can see what's under the hood. It's client-side, so you can download it and run it locally, even without an Internet connection.

So how does it work? He uses you - yes, you - as a source of entropy. It asks you to move your mouse or press random keys. You do this long enough to make it impossible to reproduce the results.

Are you interested in seeing how Bitaddress.org works? For educational purposes, we'll look at your code and try to reproduce it in Python.

Bitaddress: specifics

Bitaddress creates entropy in two forms: mouse movement and key pressure. We'll talk about both, but we'll focus on the key presses since it's difficult to implement mouse tracking in the Python Lib. We wait for the end user to enter the buttons until we have enough entropy and then we generate the key.

Bitaddress does three things. Initializes a byte array, trying to get as much entropy as possible from your computer, it populates the array with user input, and then it generates a private key.

Bitaddress uses a 256-byte array to store entropy. This array is rewritten in loops, so when the array is filled for the first time, the pointer goes to zero and the filling process starts again.

The program initiates an array with 256 bytes from window.crypto Failure It then writes a timestamp to get an additional 4 bytes of entropy. Finally, it receives data such as screen size, your time zone, information about browser plugins, your language and much more. This gives it 6 more bytes.

After initialization, the program constantly waits for user input to rewrite the original bytes. When the user moves the cursor, the program records the position of the cursor. When the user clicks the buttons, the program records the CHAR code of the clicked button.

Finally, Bitaddress uses the accumulated entropy to generate a private key. This should generate 32 bytes. For this task, Bitaddress uses an RNG algorithm called ARC4. The program initializes ARC4 with the current time and the collected entropy, then receives the bytes one by one 32 times.

This is all a simplification of how the program works, but I hope you get the idea. You can check the algorithm in full detail on Github. Disclaimer

Do it yourself

For our purposes, we'll build a simpler version of BitAddress. Firstly, we will not collect data about the user's car and location. Secondly, we will only enter the entropy via text, since it is quite difficult to get the mouse position all the time using a Python script (Check Pyautogui if you want to do this).

This brings us to the formal specification of our generator library. First, it will initialize the byte array with the cryptographic RNG, then it will populate the timestamp, and finally it will populate the user generated string. Once populated, the seed pool in the library will allow the developer to create a key. In fact, they will be able to create as many private keys as they want, all anchored by the collected entropy.

Initializing the pool

Here we put the bytes from the cryptographic RNG and the time. __seed_int and __seed_byte are two helpers that insert entropy into our pool array. Please note that we use Secrets Disclaimer

def __init_pool(self): for i in range(self.POOL_SIZE): random_byte = secrets.randbits(8) self.__seed_byte(random_byte) time_int = int(time.time()) self.__seed_int(time_int) def __seed_int(self , n): self.__seed_byte(n) self.__seed_byte(n >>8) self.__seed_byte(n >> 16) self.__seed_byte(n >> 24) def __seed_byte(self, n): self.pool[self.pool_pointer ] ^= n & 255 self.pool_pointer += 1 if self.pool_pointer >= self.POOL_SIZE: self.pool_pointer = 0

Sowing with entry

Here we first put a timestamp and then the input string, character by character.

def seed_input(self, str_input): time_int = int(time.time()) self.__seed_int(time_int) for char in str_input: char_code = ord(char) self.__seed_byte(char_code)

Generating a private key

This part may look laborious, but it's actually very simple.

First, we need to create a 32-byte number using our pool. Unfortunately, we can't just create our own Random Object and use it only for the key generation. Instead, there is a shared object that is used by any code that runs in the same script.

What does this mean for us? This means that at any given moment, anywhere in the code, one simple Random.seed(0) can destroy all of our collected entropy. We don't want this. Luckily, Python provides the Gutrite and SetState methods. So, to save our entropy every time we create a key, we remember the state we stopped and set it the next time we want to make a key.

Second, we'll just make sure our key is in the range (1, Curve_order ). This is a requirement for all ECDSA private keys. Curve_Order is the order of the TECP256K1 curve, which is FFFFFFFFFFFFFFFFFFFFFFFFFFEBAEEDCE6AF48A03BBFD25E8CD0364141 Failure

Finally, for convenience, we will convert to Hex, and split the "0x" part.

def generate_key(self): big_int = self.__generate_big_int() big_int = big_int % (self.CURVE_ORDER - 1) # key < curve order big_int = big_int + 1 # key > 0 key = hex(big_int)[2:] return key def __generate_big_int(self): if self.prng_state is None: seed = int.from_bytes(self.pool, byteorder='big', signed=False) random.seed(seed) self.prng_state = random.getstate() random. setstate(self.prng_state) big_int = random.getrandbits(self.KEY_BYTES *8) self.prng_state = random.getstate() return big_int

In action

Let's try using the library. In fact, it's really simple: you can generate a private key in three lines of code!

kg = KeyGenerator() kg.seed_input('Truly random string. I rolled a dice and got 4.') kg.generate_key() # 60cf347dbc59d31c1358c8e5cf5e45b822ab85b79cb32a9f3d98184779a9efc2

You can see this for yourself. The key is random and completely valid. Moreover, every time you run this code, you get different results.

Conclusion

As you can see, there are many ways to generate private keys. They are simple and safe.

Generating a private key is only the first step. The next step is to extract the public key and wallet address which you can use to receive payments. The wallet generation process is different for Bitcoin and Ethereum, and I plan to write two more articles on this topic.

If you want to play with the code, I've posted it to this Github Repository. Disclaimer

I'm doing a course on cryptocurrencies here on FreeCodeCamp News. The first part is a detailed description of the block.

I also post random thoughts about Crypto On Twitter so you might want to check that out.

Cloud storage Cryptomator

Cryptomator is a free tool for creating encrypted cloud storage on OneDrive, Google Drive, iCloud and on your device's hard drive.

To make a backup, install the version of Cryptomator for your operating system. The application works on Windows, macOS, Linux, Android and iOS.

Launch Cryptomator, click the Add Vault and enter the name of the vault.


Available storages are displayed on the left.

Choose a location to store your files - cloud or folder. Cryptomator will offer cloud services whose applications are installed on the device. We created storage in iCloud.


When you create a storage in the cloud, Cryptomator will write all the files into a folder that the cloud client uses for synchronization.

Set a password and enable the Yes to receive a secret phrase to recover it.


Write down the password recovery phrase in a text file or notepad.

Before you transfer the file to the storage, gain access to it: click the Unlock Now and enter the password.


The icon on the left shows the storage status: closed lock - encrypted, open - decrypted.

Cryptomator will open a virtual drive in Explorer. Place the file with the seed phrase in it. The application will immediately send it to the cloud.


Cryptomator displays the storage as a localhost virtual drive.

After that, close the vault: select it in Cryptomator and click the Lock .

If you close the application or turn off the computer, Cryptomator will automatically encrypt open storage: copy the contents of the drive to the cloud and remove the virtual device from the system.

Make a backup of your storage so you don't lose access if your device breaks down. Go to the Cryptomator folder and find the folder with the name of the vault.


Folder d contains encrypted files that will then go into storage. You cannot add anything to it manually: the cipher structure will break and the files in the storage will become unreadable.

Copy all files to an external drive. If your computer crashes, install Cryptomator on a new device and import the storage. To do this, click the Add Vault , and then Existing Vault . In the window that opens, specify the path to the masterkey and vault files.


For Cryptomator to open a backup, the folder with masterkey and vault must contain folder d with encrypted files.

When importing a vault, Cryptomator will require you to enter a password. If a hacker steals a backup, he will only gain access to your backups after a brute force attack.

Shamir's scheme in ASecuritysite

Shamir's scheme (Shamir's secret) is an algorithm that breaks information into encrypted fragments. To restore the original data, you will need several such fragments. Their number is called the threshold value.

The operation of the algorithm can be explained using the example of the problem of constructing a curve. Let's say Alice has specified five points through which only one curve passes. Bob can take the coordinates of any three points of Alice (threshold value) and construct the same curve.

A backup according to Shamir’s scheme can be made in open-source online converters. We used the first site in search results - ASecuritysite.

Go to the page with Shamir's encryption scheme. Paste the private key or seed phrase into the Secret Message .

Enter the number of fragments in the No of shares and the threshold value in the Threshold . Click the Determine .


The threshold value must be greater than 50% of the number of fragments. If there are seven fragments, set the threshold value to four; if there are eight, set the threshold value to five.

The converter will write the encrypted fragments in the Shares and separate them with the “=” sign.


The converter places the decrypted message in the Reconstructed field to prove the correct operation of the algorithm.

Save fragments on different media: write one in a notepad, the second in the cloud, the third in a password manager, etc.

A hacker will not be able to recover the data if he receives one fragment. But if you lose one fragment, you can decrypt the data to access the wallet.

To read the information in the backup, go to the page with the decoder. Paste several fragments into the Secret shares and click the Determine .


Don't forget to separate the fragments with indents so that the decoder perceives them as separate lines.

The first decryption attempts will look like sets of random bits. This is normal: the decoder tries to restore the original from the first fragment, and then adds new ones and repeats the attempts. It will issue an initial message when the threshold is reached.

Rating
( 1 rating, average 4 out of 5 )
Did you like the article? Share with friends:
For any suggestions regarding the site: [email protected]
Для любых предложений по сайту: [email protected]