Encrypted Private Keys — An outline of BIP38
As outlined in the my previous post ‘ The Maths Behind the Bitcoin Blockchain (part 1)’, a bitcoin public: private key pair is generated through Elliptic Curve Cryptography. As such, from a generator point g, and a number of point multiplications/additions n, there will be a resulting point r.
- The generator point, g, is pre-defined for the specific curve being used — in bitcoin this is secp256k1 (better known as the Kobilz curve)
- The number of point multiplications/additions, n, is the private key and must be kept secret
- The resulting point, r, is the public key and can be transformed into a bitcoin address which can be publicly shared in order to receive bitcoins
Both n and r can be represented in a number of formats e.g compressed, WIF, hex etc, which make them easier to share/read/compute with. However, regardless of the format the private key is stored in, it must be kept secret by the holder, since losing the private key means loosing access to the bitcoins sent to the associated address.
It is estimated that between 3–4m bitcoins have been rendered inaccessible due to the loss of the associated private keys.
There are a number of ways to store private keys however this can be bisected into hot and cold storage. Hot storage is where the private key is kept online e.g where an exchange has the private key in a database (encrypted or otherwise) or stored it as a note in your email drafts (please never do this) etc. Cold storage is where the private key is kept offline e.g written on a piece of paper, stored on a purpose created hardware (Trezor, Ledger etc) or engraved into a metal disc etc.
Keeping your private key in hot storage, risks its theft via hacks and online malicious actors, whereas storing it offline would require a physical theft. Neither provide absolute protection however cold storage is often hailed as the more secure storage system. But the risk remains, and if one were to gain access to your cold stored private key, then they would be able to access your bitcoins.
As a potential mitigate to this, BIP-38 was introduced in November 2011 and proposed a mechanism whereby:
a) a generated private key can be encrypted with a passphrase and therefore only those with access to the encrypted private key and the passphrase would be able to spend the associated bitcoins
b) a shared private key generation processes whereby two parties can collaborate in creating an encrypted key, with only one able to access the associated bitcoins
Let’s first look at part a) of the BIP:
a) a generated private key could be encrypted with a passphrase and therefore only those with access to the encrypted private key and the passphrase would be able to spend the associated bitcoins
This processes takes a private key and encrypts it with a passphrase, thereby producing an encrypted private key. As such, without knowledge of the passphrase, it is not possible to decrypt the resulting encrypted private key and gain access to the actual private key.
This allows someone to store the encrypted private key in cold or hot storage, safe in the knowledge that without the passphrase, no nefarious actor would be able to decrypt it and gain access to any bitcoins in the associated address.
The passphrase can be a single word or a string of words, however as with standard password hygiene, the more complex this passphrase is, the lower the chance of someone guessing or brute force attacking the encrypted private key.
Once encrypted the private key has a prefix of ‘6P’, rather than the standard wallet-import-format (WIF) private keys which start with 5 if uncompressed or ‘K’ or ‘L’ if compressed. This designates it as being encrypted and therefore illustrates that it cannot be used to spend the funds in the associated address, unless it is first decrypted with the passphrase.
Using bitaddress.org with;
— private key: L2mCw1StjvRykQThZqM4kDB6HVnvMDFoZzQK48yChTtR8Svvhs7H
— passphrase: taralovesbitcoin
We can see that the resulting BIP38 encrypted private key is: 6PYKNsNn1Fq1QrAG581zP1t1KdmPDoncTeeXnHvugPdFvxvkJWjH1DRNX1
As such, taking a private key generated through elliptic curve cryptography and encrypting with a passphrase, provides an encrypted private key which can be stored safe in the knowledge that without the associated passphrase, the associated bitcoins are safely out of reach for malicious actors. As such, the above encrypted private key can be stored safely in hot or cold storage since without knowing the passphrase ‘taralovesbitcoin’ then it cannot be decrypted back into the raw private key which is required to access any associated bitcoins.
We will now look at part b) of BIP38, a process which is often overlooked when discussing this seminal bitcoin improvement proposal.
b) a shared private key generation processes whereby two parties can collaborate in creating an encrypted key, with only one able to access the associated bitcoins
Whereas part a) allowed for an already generated private key to be encrypted, part b) allows for a processes whereby two parties can collaborate to create an encrypted key, with only one having the knowledge of the passphrase required to spend any associated bitcoins.
Encrypting a private key with EC multiplication offers the ability for someone to generate encrypted keys knowing only an EC point derived from the original passphrase and some salt generated by the passphrase’s owner, and without knowing the passphrase itself. Only the person who knows the original passphrase can decrypt the private key. A code known as an intermediate code conveys the information needed to generate such a key without knowledge of the passphrase.
There are two parties for this process; an owner and a printer. The printer helps create the private key but only has knowledge of the encrypted version and the owner is the end recipient of the private key and therefore is able to access the decrypted version.
Alice is the owner and Bob is the printer.
The Process
Step 1) Alice must first generate an intermediate code. She shares this with Bob.
Step 2) Bob uses the intermediate code to generate an encrypted key pair and gives this to Alice
Step 3) Alice is able to decrypted this key pair to have access to a public: private key pair
In the above process, Alice and Bob have co-created a public:private key pair with Bob only able to access the encrypted version.
Let’s dig into this process a little more…
Step 1) Alice must first generate an intermediate code. She shares this with Bob.
First Alice must generate 8 random bytes, known as the ownersalt. Then using the key derivation algorithm called Scrypt with the ownersalt and a passphrase she determines, she creates a 32-byte key. This is called the passfactor.
Next Alice computes the elliptic curve point G multiplied by the passfactor and converts the result to a 33 byte compressed notation. This is called the passpoint.
Both the ownersalt and passpoint are shared with the printer, Bob, ideally in base58 notation. This known as the intermediate_passphrase_string.
Step 2) Bob uses the intermediate code to generate an encrypted key pair and gives this to Alice
Given the intermediate_passphrase_string from Alice, Bob knows the passpoint and the ownersalt but does not know Alice’s passphrase or the passfactor. From this he needs to generate an encrypted kay pair to give back to Alice.
He therefore follows the following process:
a) Set FlagByte
If Alice’s end bitcoin address will be in the compressed format then the bit 0x20 will need to be selected. If, within this process, a number of keys are to be derived, then lot and sequence numbers must be generated and bit 0x04 turned on. However, for a simplified explanation here, only one key will be derived, as such the lot and sequence number steps have been ommitted.
b) Generate the factorb
This is taken after choosing a random 24 byte string called the seedb and running the SHA256 algorithm twice upon it: SHA256(SHA256(seedb)). The result is a 32 byte string known as the factorb.
c) Generate a bitcoin address
Computing elliptic curve multiplication on the passpoint and factorb will result in a co-ordinate (x,y) on the elliptic curve. This is a public key and can be hashed to form a bitcoin address, which we shall refer to here as generatedaddress.
Now taking the first 4 bytes of SHA256(SHA256(generatedaddress) = addresshash
d) Derive a second key from the passpoint
Using the Scrypt algorithm again and the seedb we derive another key which we split into two 32 byte halves. These are the derivedhalf1 and dervivedhalf2.
e) Encrypt both derived halves separately
The Advanced Encryption Standard (AES) is an encryption algorithm whereby the same key is used to both encrypt and decrypt, as such it is known as symmetric key encryption. Using AES, the derived halves are encrypted;
- AES256Encrypt(block = (seedb[0…15] xor derivedhalf1[0…15]), key= derivedhalf2)
The 16 byte result is called encryptedpart1
- AES256Encrypt(block = ((encryptedpart1[8…15] + seedb[16…23]) xor derivedhalf1[16…31]), key = derivedhalf2)
The 16 byte result is called encryptedpart2
We now concatenate into a base58 check-encoded private key
0x01 0x43 + flagbyte + addresshash +encryptedpart1[0…7]+encryptedpart2
Bob, our printer, can now send a confirmation code and this encrypted private key back to Alice, the owner. She is able to verify that a bitcoin address has been generated and it is derived from her passphrase which only she knows.
The obvious question is then, why and when is this used?
BIP38’s primary use is for paper wallets and physical bitcoins, since storing the private key physically still leaves it at risk of theft. As such the methods described ensure that with a passphrase and the record string, the private key can always be reconstituted (using the protections of salting and scrypt to guard against brute-force attacks).
However, whilst part a) of BIP38 allows for an existing private key to be encrypted, part b) introduces a shared private key generation process which could be used by a physical bitcoin manufacturer to co-create a key pair without the risk of anyone other than the end user being able to know the private key. Whilst this may be a complex process for someone wishing to generate a small number of bitcoin addresses/private keys, for those who require a larger number or more frequent key generation, this co-creation process could be more efficient.