diff --git a/scripts/common/PasswordFunctions.py b/scripts/common/PasswordFunctions.py new file mode 100644 index 0000000000..36fbd43be7 --- /dev/null +++ b/scripts/common/PasswordFunctions.py @@ -0,0 +1,7 @@ +from Crypto.Hash import keccak + +def hash_password(password, old_desktop=False): + hasher = keccak.new(digest_bits=256) + hasher.update(password.encode()) + hash = hasher.hexdigest() + return '0x' + (hash.upper() if old_desktop else hash.lower()) diff --git a/scripts/common/__init__.py b/scripts/common/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/scripts/open_database.py b/scripts/open_database.py new file mode 100644 index 0000000000..26634ff56e --- /dev/null +++ b/scripts/open_database.py @@ -0,0 +1,106 @@ +import sys, os, re +import sqlcipher3 +from getpass import getpass +from common import PasswordFunctions + +def open_db(file_path, passwordHash: str, kdfIterations: int): + db = sqlcipher3.connect(file_path) + pageSize = 8192 if file_path.endswith("-v4.db") else 1024 + + print(f'> Opening database. Selected cipher_page_size: {pageSize}') + db.execute(f'PRAGMA key = "{passwordHash}"') + db.execute(f'PRAGMA cipher_page_size = {pageSize}') #1024 for older db, 8192 for newer + db.execute(f'PRAGMA kdf_iter = {kdfIterations}') + db.execute('PRAGMA cipher_hmac_algorithm = HMAC_SHA1') + db.execute('PRAGMA cipher_kdf_algorithm = PBKDF2_HMAC_SHA1') + # db.execute('PRAGMA cipher_compatibility = 3;') + + return db + +class Account: + def __init__(self, name, keyUid, kdfIterations): + self.name = name + self.keyUid = keyUid + self.kdfIterations = kdfIterations + + def __str__(self): + return f"{self.name} - {self.keyUid}, kdfIterations: {self.kdfIterations}" + +class Config: + def __init__(self): + self.args = sys.argv[1:] + + def input_base_path(self): + if len(self.args) > 0: + self.base_path = self.args[0] + else: + self.base_path = input('> Input a base path: ') + if not self.base_path.endswith('/'): + self.base_path += '/' + + def read_accounts(self): + db = sqlcipher3.connect(self.base_path + '/accounts.sql') + accounts = db.execute('SELECT name, keyUid, kdfIterations FROM accounts').fetchall() + db.close() + + if len(accounts) == 0: + print("no accoutns found") + exit(0) + + self.accounts = [] + print(f'> Accounts found: ') + for i, a in enumerate(accounts): + account = Account(a[0], a[1], a[2]) + self.accounts.append(account) + print(f'{i}: {str(account)}') + + def find_database(self): + regex = re.compile(f'{self.selectedAccount.keyUid}(\-v4)?.db$') + for _, _, files in os.walk(self.base_path): + for file in files: + if regex.match(file): + return file + return '' + + def select_account(self): + if len(self.args) > 1: + self.account_index = int(self.args[1]) + else: + self.account_index = int(input('> Select an account by index: ')) + self.selectedAccount = self.accounts[self.account_index] + self.database_path = self.base_path + self.find_database() + print(f'selected database: {self.database_path}') + + def input_password(self): + if len(self.args) > 2: + password = self.args[2] + else: + password = getpass("> Input password: ") + config.password_hash = PasswordFunctions.hash_password(password, old_desktop=False) + + +config = Config() +config.input_base_path() +config.read_accounts() +config.select_account() +config.input_password() + +## Select and open database + +db = open_db(config.database_path, config.password_hash, config.selectedAccount.kdfIterations) + +## use the `db` instance to execute queries + +tables = db.execute("SELECT name FROM sqlite_master WHERE type='table';").fetchall() +print(f"> Database opened. {len(tables)} tables found.") + +## loop sql operations + +while True: + cmd = input("SQL> ") + if cmd == "exit": + break + output = db.execute(cmd).fetchall() + print(output) + +db.close() diff --git a/scripts/password-hash.py b/scripts/password-hash.py index d6830d72bc..55e287f949 100644 --- a/scripts/password-hash.py +++ b/scripts/password-hash.py @@ -1,12 +1,9 @@ -import sha3 import pyperclip +from common import PasswordFunctions print("Type your password...") password = input() - -hasher = sha3.keccak_256() -hasher.update(password.encode()) -hash = '0x' + hasher.hexdigest() +hash = PasswordFunctions.hash_password(password) pyperclip.copy(hash) - print(f'Hash: {hash} is copied to clipboard') +