diff --git a/doc/NEWS b/doc/NEWS index 381a1e456e..f033a23b6b 100644 --- a/doc/NEWS +++ b/doc/NEWS @@ -450,6 +450,8 @@ Major changes from 1.9.0-jumbo-1 (May 2019) in this bleeding-edge version: project in August 2020 by supporting (and distinguishing) both our meaning (bcrypt-pbkdf + AES-256-CTR) and theirs (MD5 + single DES). [Solar; 2025] +- bitcoin2john.py: add support SQLite3 format [Maxim Kuleshov; 2025] + Major changes from 1.8.0-jumbo-1 (December 2014) to 1.9.0-jumbo-1 (May 2019): diff --git a/doc/README.bitcoin b/doc/README.bitcoin index 7d1fa734dc..32ee0e718b 100644 --- a/doc/README.bitcoin +++ b/doc/README.bitcoin @@ -17,6 +17,9 @@ This procedure also works with many altcoins historically forked from Bitcoin. The bitcoin2john.py script is compatible with both Python 2 and Python 3. +Bitcoin Core 0.21.0 and above uses SQLite3 for new wallets. In this case, +Berkeley DB support is not required. + Since Python 3 no longer provides Berkeley DB support out of the box, to get the script to work with Python 3 you need to install the corresponding module: diff --git a/run/bitcoin2john.py b/run/bitcoin2john.py index fa0297fbbf..afa710d0e6 100755 --- a/run/bitcoin2john.py +++ b/run/bitcoin2john.py @@ -4,6 +4,7 @@ # Copyright (c) 2012-2018 Dhiru Kholia # Copyright (c) 2019 Solar Designer # Copyright (c) 2019 exploide +# Copyright (c) 2025 Maxim Kuleshov # Redistribution and use in source and binary forms, with or without # modification, are permitted. (This is a heavily cut-down "BSD license".) # @@ -30,16 +31,24 @@ import logging import struct import sys +import sqlite3 -try: - from bsddb.db import * -except: - try: - from bsddb3.db import * - except: - sys.stderr.write("Error: This script needs bsddb3 to be installed!\n") - sys.exit(1) +bsddb_db = None + +def do_import_bsddb(): + global bsddb_db + if bsddb_db is not None: + return + + try: + import bsddb.db as bsddb_db + except: + try: + import bsddb3.db as bsddb_db + except: + sys.stderr.write("Error: This script needs bsddb3 to be installed!\n") + sys.exit(1) json_db = {} @@ -114,13 +123,35 @@ def _read_num(self, format): self.read_cursor += struct.calcsize(format) return i +class Sqlite3DB: + def __init__(self, walletfile): + self.cx = sqlite3.connect(walletfile) + + def is_sqlite3(self): + try: + self.cx.execute("PRAGMA quick_check") + return True + except sqlite3.DatabaseError: + return False + + def close(self): + self.cx.close() + + def items(self): + return list(self.cx.execute('SELECT key,value FROM main')) + def open_wallet(walletfile): - db = DB() - DB_TYPEOPEN = DB_RDONLY - flags = DB_THREAD | DB_TYPEOPEN + db = Sqlite3DB(walletfile) + if db.is_sqlite3(): + return db + + do_import_bsddb() + db = bsddb_db.DB() + DB_TYPEOPEN = bsddb_db.DB_RDONLY + flags = bsddb_db.DB_THREAD | DB_TYPEOPEN try: - r = db.open(walletfile, "main", DB_BTREE, flags) - except DBError as e: + r = db.open(walletfile, "main", bsddb_db.DB_BTREE, flags) + except bsddb_db.DBError as e: logging.error(e) r = True