Python Blockchain

Dump Unencrypted Bitcoin Wallet.dat

This script scans a wallet.dat file for ECDSA private keys using memory mapping. It generates the corresponding compressed/uncompressed Bitcoin addresses and WIF (Wallet Import Format) keys.

⚠️ Warning: Use only on wallets you own. Works on unencrypted files only.

import binascii
import hashlib
import codecs
import mmap
import sys
import ecdsa
import base58  # pip install base58

def base58str(address_hex):
    alphabet = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
    b58_string = ''
    leading_zeros = len(address_hex) - len(address_hex.lstrip('0'))
    address_int = int(address_hex, 16)
    while address_int > 0:
        digit = address_int % 58
        digit_char = alphabet[digit]
        b58_string = digit_char + b58_string
        address_int //= 58
    ones = leading_zeros // 2
    for one in range(ones):
        b58_string = '1' + b58_string
    return b58_string

def priv_to_addr(address_hex, compressed):
    signing_key = ecdsa.SigningKey.from_string(address_hex, curve=ecdsa.SECP256k1)
    verifying_key = signing_key.get_verifying_key()
    if not compressed:
        public_key = bytes.fromhex("04") + verifying_key.to_string()
    else:
        public_key_x = verifying_key.to_string()[0:32]
        public_key_y = verifying_key.to_string()[32:]
        if int(binascii.hexlify(public_key_y),16) % 2 == 0:
            public_key = bytes.fromhex("02") + public_key_x
        else:
            public_key = bytes.fromhex("03") + public_key_x
    sha256_1 = hashlib.sha256(public_key)
    ripemd160 = hashlib.new("ripemd160")
    ripemd160.update(sha256_1.digest())
    hashed_public_key = bytes.fromhex("00") + ripemd160.digest()
    checksum_full = hashlib.sha256(hashlib.sha256(hashed_public_key).digest()).digest()
    checksum = checksum_full[:4]
    bin_addr = hashed_public_key + checksum
    result_addr = base58.b58encode(bin_addr).decode("utf-8")
    return result_addr

def main():
    if len(sys.argv) < 2:
        print("Usage: python dump_wallet.py wallet.dat")
        sys.exit(1)

    f = open(sys.argv[1], "rb")
    mm = mmap.mmap(f.fileno(),0,prot=mmap.PROT_READ)
    
    # Scanning for key patterns
    currindex = mm.find(b'\x02\x01\x01\x04\x20')
    privkeyList = set()
    
    while(currindex > -1):
        mm.seek(currindex+5)
        privkeyList.add(mm.read(32))
        currindex = mm.find(b'\x02\x01\x01\x04\x20', currindex+1)
    f.close()
    
    print(f"Found {len(privkeyList)} possible keys")

    for key in privkeyList:
        PKuncomp = b'80'+ binascii.hexlify(key)
        uncomp_address = priv_to_addr(key, False)
        
        PKuncomp_sha256_1 = hashlib.sha256(codecs.decode(PKuncomp, 'hex'))
        PKuncomp_sha256_2 = hashlib.sha256(PKuncomp_sha256_1.digest())
        checksum_uncomp = codecs.encode(PKuncomp_sha256_2.digest(), 'hex')[0:8]
        uncomp_PK = PKuncomp + checksum_uncomp
        WIF_uncomp = base58str(uncomp_PK.decode("utf-8"))
        
        print(f"{uncomp_address}:{WIF_uncomp}")

if __name__ == "__main__":
    main()

Requirements

  • 1. Python 3.x installed
  • 2. pip install ecdsa base58
  • 3. An unencrypted wallet.dat file

How to Run

python wallet_dump.py wallet.dat > keys.txt