Bitcoin Forum
November 02, 2025, 12:30:08 PM *
News: Latest Bitcoin Core release: 30.0 [Torrent]
 
   Home   Help Search Login Register More  
Pages: [1]
  Print  
Author Topic: Pre bitcoin 0.4 encryption  (Read 288 times)
junior_clk (OP)
Jr. Member
*
Offline Offline

Activity: 30
Merit: 2


View Profile
August 20, 2025, 12:00:16 AM
 #1

in bitcoin 0.4 it uses private key encryption as mentions below
Does either multibit or BitcoinJ pre bitcoin 0.4 any of them developed in 2011 use the same encryption?
I read they both use AES but can't find the discussion in the Bitcoinj google group

The real question is how does the private key encryption/decryption work and what is used?
I got 34 characters (base 58/64) 16 characters (what could be the salt?) and a 0x8d total of 42 characters



/*
Private key encryption is done based on a CMasterKey,
which holds a salt and random encryption key.

CMasterKeys is encrypted using AES-256-CBC using a key
derived using derivation method nDerivationMethod
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.
vchOtherDerivationParameters is provided for alternative algorithms
which may require more parameters (such as scrypt).

Wallet Private Keys are then encrypted using AES-256-CBC
with the double-sha256 of the private key as the IV, and the
master key's key as the encryption key.
*/
programmer3666
Full Member
***
Offline Offline

Activity: 252
Merit: 115



View Profile
August 20, 2025, 05:28:32 PM
Merited by vapourminer (2)
 #2

in bitcoin 0.4 it uses private key encryption as mentions below
Does either multibit or BitcoinJ pre bitcoin 0.4 any of them developed in 2011 use the same encryption?
I read they both use AES but can't find the discussion in the Bitcoinj google group

The real question is how does the private key encryption/decryption work and what is used?
I got 34 characters (base 58/64) 16 characters (what could be the salt?) and a 0x8d total of 42 characters



/*
Private key encryption is done based on a CMasterKey,
which holds a salt and random encryption key.

CMasterKeys is encrypted using AES-256-CBC using a key
derived using derivation method nDerivationMethod
(0 == EVP_sha512()) and derivation iterations nDeriveIterations.
vchOtherDerivationParameters is provided for alternative algorithms
which may require more parameters (such as scrypt).

Wallet Private Keys are then encrypted using AES-256-CBC
with the double-sha256 of the private key as the IV, and the
master key's key as the encryption key.
*/


This topic caught my attention for a chicky reasons Cheesy. bitcoin 0.4 actually did bring in AES-256-CBC with the CMasterKey salt ++ random key whereas private keys were encrypted with doubled SHA256 of the key as Iv... and for bitcoinJ / multibit at about around 2011 they also used AES but not in the exact same way as core becuase core kinda depended on OpenSSL EVP functionx while bitcoinJ in the other hand make use of Java crypto librariess. that 34 + 16 + 0x8d you mentioned does line up with how core wallet dumps actualy looked back then

Funny  story  Grin in my first semester of MSc CyberSecurity Science we actually did practicals on AES,, salt & IVs  Although at the time!! it kind of felt like old school crypto theory beacuse sincerely speaking my university still dwells a lot on knownledge that feels expired, but discussions like this show how those fundamentals back then!!  directly apply to real systems like Bitcoin wallets... So i think it is safe to say no knowledge is a waste after all Grin.

junior_clk (OP)
Jr. Member
*
Offline Offline

Activity: 30
Merit: 2


View Profile
August 20, 2025, 08:56:54 PM
Last edit: August 21, 2025, 09:42:41 AM by Mr. Big
Merited by Cricktor (1)
 #3

Yes Programmer found out that multibit until 0.3.x and bitcoinj 0.5 use the same encryption for the private keys
I thought it was from openssl but you I didn't learn what you learned, I'm no programmer at all
just playing with computers from 6 years old on a commodore and on

I found https://github.com/Multibit-Legacy/multibit/wiki/Export%20and%20limited%20import%20of%20private%20keys
And there it states it does use openssl?

and found some python code for decrypting but that's over my head
https://github.com/gurnec/decrypt_bitcoinj_seed/tree/master/aespython
https://github.com/serprex/aespython
https://github.com/HardCorePawn/multibit_recovery/tree/master



thanks for your reaction, most users questioned my answers, because it couldn't be.
For standard bitcoin indeed or bitcoin 0.4+
Maybe you have the solution I need?

Couldn't send you a private message because i'm a newbie at the forum
Thnx anyway
programmer3666
Full Member
***
Offline Offline

Activity: 252
Merit: 115



View Profile
August 23, 2025, 11:14:47 PM
 #4

Yes Programmer found out that multibit until 0.3.x and bitcoinj 0.5 use the same encryption for the private keys
I thought it was from openssl but you I didn't learn what you learned, I'm no programmer at all
just playing with computers from 6 years old on a commodore and on

I found https://github.com/Multibit-Legacy/multibit/wiki/Export%20and%20limited%20import%20of%20private%20keys
And there it states it does use openssl?

and found some python code for decrypting but that's over my head
https://github.com/gurnec/decrypt_bitcoinj_seed/tree/master/aespython
https://github.com/serprex/aespython
https://github.com/HardCorePawn/multibit_recovery/tree/master

<<Edited Out>>

You are very welcome bro!! I even took the liberty of going through the repos you shared, it is a bit funny you said you are no programmer but no issues i will make it a bit simple as to how they tied together.. the https://github.com/gurnec/decrypt_bitcoinj_seed/tree/master/aespython is specifically designed for decryptin BIP39 / 44 wallet seeds that MultiBitHD will use.. it is more like replicating the same logic bitcoinJ use for wallet encryption.. and for the https://github.com/HardCorePawn/multibit_recovery/tree/master it is more of a full recovery utility for MultiBit wallet files so while the first repo is more focused on the seed only!! this one deals more with the actual wallet files and also the recovery.. and for this repo https://github.com/serprex/aespython it is just a pure python AES implementation basically use during testing so as to avoid external crypto libraries and it also ensure compatibility..it is just what the other tools are suppose to rely on when the OpenSSL bindings is not available..

Look sorry the technical jargos is even a bit much but in a very simple language though.. all this repos are just doing the same kind of job!! like helping to recover old multiBit wallets... Like first repo link i talk about is focusing on unlocking the seed / the master key and the second one is more like a full recovery tool for wallet files and while the third one is just showing how the encryption itself works behind.. so the tools are just doing the Mike Tyson kind of job behind the scene!! like they basically handle the heavy lifting for you and allow you chill with a cup of coffee!!! all you will do is just to give them your wallet file ++ password and they will try to rebuild or unlock your coins no questions asked...

junior_clk (OP)
Jr. Member
*
Offline Offline

Activity: 30
Merit: 2


View Profile
August 25, 2025, 12:24:07 AM
Last edit: August 25, 2025, 12:48:02 AM by junior_clk
Merited by BattleDog (1)
 #5

I couldn't get anything to work, so I asked chatgpt to make some python files
To be clear, I dont have any files, just the 34 character and 16 character I noted as secret key
That seemed enough back then (bitcoin 0.3.24 with nodejs or bitcoinj or something, I'm very sure its pre bitcoin 0.4)
If I base64 hex the secret key it gives ECA***********CD********* the * is 10 numbers and 9 numbers

# -*- coding: utf-8 -*-
import base64
from Crypto.Cipher import AES

BLOCK = 16

def fix_base64(b64):
    """Voeg ontbrekende = padding toe"""
    return b64 + "=" * ((4 - len(b64) % 4) % 4)

def decrypt_legacy(secret, b64, debug=True):
    """AES decryptie zoals BitcoinJ pre-2012"""
    key = secret  # in Python 2, str is al bytes
    b64_fixed = fix_base64(b64)
  
    if debug:
        print "[DEBUG] Base64 input:", b64
        print "[DEBUG] Base64 padded:", b64_fixed

    data = base64.b64decode(b64_fixed)
    if debug:
        print "[DEBUG] Ciphertext length:", len(data), "bytes"
        print "[DEBUG] Ciphertext hex:", data.encode('hex'))

    for mode in ("ECB", "CBC0"):
        try:
            if mode == "ECB":
                cipher = AES.new(key, AES.MODE_ECB)
                pt = cipher.decrypt(data)
            else:
                iv = "\x00" * BLOCK
                cipher = AES.new(key, AES.MODE_CBC, iv)
                pt = cipher.decrypt(data)

            if debug:
                print "[DEBUG] Mode", mode, "decrypted length:", len(pt)
                print "[DEBUG] Raw plaintext hex:", pt.encode('hex')

            pad = ord(pt[-1])
            if 1 <= pad <= BLOCK and pt.endswith(chr(pad) * pad):
                pt = pt[:-pad]
                if debug:
                    print "[DEBUG] Padding", pad, "removed, new length:", len(pt)

            if len(pt) == 32:
                if debug:
                    print "[SUCCESS] Decrypted private key found!"
                return pt
        except Exception as e:
            if debug:
                print "[DEBUG] Exception in mode", mode, ":", e)
            continue
    return None

if __name__ == "__main__":
    secret = "7ABCDEFGHIJKLMNO"  # jouw 16-char secret
    encrypted_key = "3CaUUDLAgGNvNL1gh1B*******prWtnuiH"  # 34-char string

    priv = decrypt_legacy(secret, encrypted_key, debug=True)
    if priv:
        print "[RESULT] Private key (hex):", priv.encode('hex')
    else:
        print "[RESULT] Kon de sleutel niet ontsleutelen."

and some other, but chatgpt couldnt figure it out, but I know for sure the encrypted key from a few lines above this is correct, the secret key isn't but that shouldn't matter, chatgpt said it doesnt matter if its python 2 or 3 while I read that does matter with the string being for python2 and not 3
BattleDog
Member
**
Offline Offline

Activity: 75
Merit: 112


View Profile
September 08, 2025, 04:11:47 PM
Merited by vapourminer (1)
 #6

A few facts that should clear this up and save you some rabbit holes:

Pre-0.4.0 Core had no wallet encryption. Bitcoin Core 0.3.x stored private keys in Berkeley DB as key/wkey (unencrypted). "Encryption" only appears in 0.4.0.

Core 0.4+ encryption (wallet.dat) works the following way:

-- A random 32-byte master key is generated.
-- Your passphrase is run through EVP_BytesToKey(SHA-512) with an 8-byte salt and a stored, wallet-specific nDeriveIterations (chosen to take ~250ms on your machine when you encrypted). These three values live in the mkey record: vchSalt, nDeriveMethod (0=SHA-512), nDeriveIterations, and vchCryptedKey (the master key encrypted with AES-256-CBC).
-- Each private key is then stored as ckey = AES-256-CBC(master_key, IV) of the secret, where IV = first 16 bytes of DoubleSHA256(pubkey).
-- If you see key entries, they're unencrypted; ckey means encrypted; mkey must be present for encrypted wallets.

So, Core doesn't encrypt each key with your passphrase directly; it encrypts a master key with your passphrase, and uses that master key to encrypt each private key.

bitcoinj (0.5 era) is not the same scheme, bitcoinj's default KeyCrypterScrypt uses scrypt (N=16384, r=8, p=1) to derive an AES-256 key, and (by default) encrypts each key with AES using a random IV per key. Different KDF, different layout, different metadata. Don't mix the two.

You can inspect your files quickly by dumping the Berkeley DB and looking for records: mkey (has salt+iterations), ckey (encrypted privkeys), key (plain). Tools you can use: bitcoin-wallet -wallet=<path> -dump on modern Core; or pywallet/simple BDB dumper if you're working offline. Do not post the file.


Now, about your Python attempt, brute-forcing AES on ckey with guesses about fixed IV/format will fail unless you first decrypt the master key using the exact SHA-512 KDF params from mkey.
For bitcoinj wallets, use scrypt with the wallet's salt, then try AES with the per-entry IV. Different code path entirely.


If you want, you can paste (in text) the mkey fields (salt hex + nDeriveIterations + nDeriveMethod) and a single ckey+pubkey pair from a test wallet (no funds) and then I can help you sketch the decryption steps so your script checks the right boxes.

Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.19 | SMF © 2006-2009, Simple Machines Valid XHTML 1.0! Valid CSS!