Author

Topic: Wallet encryption process (Read 496 times)

member
Activity: 122
Merit: 37
January 28, 2023, 02:36:31 AM
#8
As NotATether says first you need the AES key. Without that, forget it.
If you have the AES key, then take the public key of the Ckey and perform a SHA256 on it twice. (The public key is in the wallet dump below the Ckey)

The first 16 bytes of the hash are the IV for the AES. Then you do an AES decrypt with the Ckey, IV and AES key.
The first 32 bytes of the result is the private key for that Ckey. Example using the dummy AES key from the original post:

master key    5c5692daff165d3d32e5c05a56dde3b2d0ebc05f133f8d0616941e9abe7e0fb0
Ckey              316787cf83a3c9caeca2a2b20f0879edc2a8c60ed127453c00330d1ac009402d78eff292b03e588 a3b858410ea2628ed
public key      027a098dbada15a831c66491cb20dee174d4971fdd9766a3b6c3dc64562cbb6524

SHA256 x 2   e8fd42dda81c80d956998c05238a12d7ea58c971d31a1640f1ef51df47277b90

AES key    5c5692daff165d3d32e5c05a56dde3b2d0ebc05f133f8d0616941e9abe7e0fb0
IV             e8fd42dda81c80d956998c05238a12d7 and the Ckey

Result        e1f08760a5dbfa7fc0b7f2d1864fbd8c31180b7cc8f87d2e8c1c892bc1ced5a0101010101010101 01010101010101010
Private key e1f08760a5dbfa7fc0b7f2d1864fbd8c31180b7cc8f87d2e8c1c892bc1ced5a0
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
November 02, 2022, 05:28:25 PM
#7

# Decrypting Ckeys will be the subject of another post.


I'd be interested in the process for decrypting ckeys for Bitcoin

There's no way to do that without the AES key. There are no known flaws in the algorithm you could exploit.

Besides, these steps usually do not encrypt the wallet file per se, they encrypt specific values within the wallet (usually private keys), because wallet files are often just databases such as sqlite and BDB.
newbie
Activity: 1
Merit: 0
October 30, 2022, 08:11:17 PM
#6

# Decrypting Ckeys will be the subject of another post.


I'd be interested in the process for decrypting ckeys for Bitcoin
HCP
legendary
Activity: 2086
Merit: 4361
April 18, 2021, 04:45:43 AM
#5
I had been wondering about the process of encrypting a wallet but could not find a simple enough explanation of how it works (I am a newbie!) So I thought I would do some investigating.
It should be noted that this is just one method of encrypting a wallet... Not all wallets employ this particular method of encryption.

Indeed it seems that this is the method specifically employed by Bitcoin Core for encrypting private key data in the wallet.dat file.
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
April 18, 2021, 03:28:04 AM
#4
I am currently brute forcing a Bitcoin hash for somebody and can go through 300 million combinations in about half a day using Hashcat.
Do you know what the steps are? I mean is it just SHA2 hash/hmac + KDF or is there more including AES decryption and maybe address creation because I'm trying to figure out why you get ~7000 combinations per second only (it seems too low if the steps are the former).

I'm actually getting 4500 combinations/second so my numbers are slightly off. 300 million words was a really bad estimate off by a few dozen million.

It's PBKDF2-HMAC-SHA512 key stretching only, the input hash does not contain the encryption data for AES.

I believe a custom iteration count is used for each wallet file, for example my hash uses 207301 iterations.
legendary
Activity: 3472
Merit: 10611
April 18, 2021, 02:39:45 AM
#3
I am currently brute forcing a Bitcoin hash for somebody and can go through 300 million combinations in about half a day using Hashcat.
Do you know what the steps are? I mean is it just SHA2 hash/hmac + KDF or is there more including AES decryption and maybe address creation because I'm trying to figure out why you get ~7000 combinations per second only (it seems too low if the steps are the former).
legendary
Activity: 1568
Merit: 6660
bitcoincleanup.com / bitmixlist.org
April 18, 2021, 02:14:22 AM
#2
Quote
Code:
# Hashing with SHA512. This process generates the wallet key and IV. It is one-way. You cannot go back from
# here to recover the password, which is why it is so important you remember it.
# It is also essential the password is strong because this is where dictionary attacks can take place.
# Remember the salt & iterations are recoverable from the wallet.dat files!

Not just strong, it's got to be absurdly long like >40 characters or a shorter number of completely random characters.

I am currently brute forcing a Bitcoin hash for somebody and can go through 300 million combinations in about half a day using Hashcat. The word list was assembled by combining other short words, symbols and separators (like space ' ', period and exclamation mark) with each other to make groups of 1-4 words stuck together.

So, somebody with a list of tokens that you might use can exhaust a frighteningly large space of passwords it could've been, which is why it's important to use a random password or a very long password for wallet.dat files especially.
member
Activity: 122
Merit: 37
April 18, 2021, 12:55:28 AM
#1
I had been wondering about the process of encrypting a wallet but could not find a simple enough explanation of how it works (I am a newbie!) So I thought I would do some investigating. The result was that I put together a little python script which explains it to me. I thought I would post it here in case it is of use to others. The base code came from
https://stackoverflow.com/questions/61378005/decrypting-aes-256-cbc-cipher-with-a-passcode-built-using-pbkdf2-in-python. The rest of the information I pieced together from various places on the internet. The explanation is in the code. Install the dependencies, run it, look at the results and then read through the heavily commented code to understand the process. If I have made any mistakes, please let me know.

Code:
from base64 import b64encode
import hashlib
import binascii
import pyaes
import os
import random

# Wallet software generates a random 32 byte master key. (How this is done is well documented and is not
# explained here). The master key needs to be encrypted to protect your funds. The one below is made up.
# You can substitute your own key below to try the software but DO NOT publish your own key anywhere.
mkey = binascii.unhexlify("5c5692da0f165d3d32e5c05a56dde9b2d0ebc05f100f8d0616941e9abe7e0fb0")

# Wallet software will ask you for a password to encrypt the master key.
# You can change the password below for your own, but don't lose the b in front.
password = b'password123'

# Also needed is some 'randomness' in the form of a salt and an iteration count. These are generated by the wallet.
# Use the # to comment out the salt and iteration count below if testing your own values.

# create a random 8 byte salt and iteration count.
salt = os.urandom(8)
iterationcount = random.randint(2500, 50000)
# These two values are saved in wallet.dat so that the wallet key can be recreated (not decrypted) if you know the password.

# here you can substitute your own salt and iteration count from a wallet. Remove the # in front
#salt = binascii.unhexlify('a49e804e25740714')
#iterationcount = 91005

# Now if you run the program several times, you will see you get different wallet keys for the same password.
# The random salt and iterations help prevent duplicate wallet keys for the same password.

# Hashing with SHA512. This process generates the wallet key and IV. It is one-way. You cannot go back from
# here to recover the password, which is why it is so important you remember it.
# It is also essential the password is strong because this is where dictionary attacks can take place.
# Remember the salt & iterations are recoverable from the wallet.dat files!
hash512 = hashlib.pbkdf2_hmac('sha512', password, salt, iterationcount)

# The wallet key is the first 32 bytes of the hash.
wallet_key = hash512[0:32]
# The IV (initialization vector) is the next 16 bytes of the hash
iv = hash512[32:48]

# We now have all we need to encrypt the master key
# Encryption with AES-256-CBC
encrypter = pyaes.Encrypter(pyaes.AESModeOfOperationCBC(wallet_key, iv))
ciphertext = encrypter.feed(mkey)
ciphertext += encrypter.feed()
# The cipher text is what you see in the wallet.dat files as Mkey followed by 48 bytes
# There are also Ckey's which hold the private spend keys for each address.
#######################################################################################
# Your master private key is now encrypted!!
#######################################################################################
# Decryption is the reverse process using the same wallet key and IV to process the ciphertext (Mkey)

# Decryption with AES-256-CBC
decrypter = pyaes.Decrypter(pyaes.AESModeOfOperationCBC(wallet_key, iv))
decryptedData = decrypter.feed(ciphertext)
decryptedData += decrypter.feed()
# The master key is now decrypted for all the world to see.
# However, before we can spend any funds we need to decrypt the Ckeys which hold the private keys to the addresses
# As you can see with no Ckey's, wallet recovery services cannot access your funds. It is safe to send Mkey ciphertext
# iteration count and salt but not the wallet itself as this has ALL the keys.
# Decrypting Ckeys will be the subject of another post.

# If you have found this useful please consider a small BTC tip to bc1qg82720gvdyvnc3jycnun348fhs3qam44nsmeqm

# Display results
def printData(text, data):
    print(text + " (hex)   :" + data.hex())
    print(text + " (Base64):" + b64encode(data).decode('utf8') + "\n")


printData("SHA512    ", hash512)
printData("Wallet Key", wallet_key)
printData("16 bytes IV", iv)
printData("Master Key ", mkey)
printData("Ciphertext ", ciphertext)

# Decrypted data
printData("Decrypted  ", decryptedData)

 
Jump to: