From 2b20456d344398b1b2c8fa6642ea0ba12da233f8 Mon Sep 17 00:00:00 2001 From: lthievenaz-keeper Date: Fri, 24 Jul 2026 16:40:01 +0100 Subject: [PATCH 1/3] Add support for keepass-key-file arg We support key files for the import, but not for the export. Added an arg to export for passing the keyfile path directly. --- keepercommander/importer/commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/keepercommander/importer/commands.py b/keepercommander/importer/commands.py index 23245f743..5fae4198a 100644 --- a/keepercommander/importer/commands.py +++ b/keepercommander/importer/commands.py @@ -97,6 +97,8 @@ def register_command_info(aliases, command_info): help='Maximum file attachment file. Example: 100K, 50M, 2G. Default: 10M') export_parser.add_argument('-kp', '--keepass-file-password', dest='file_password', action='store', help='Password for the exported file') +export_parser.add_argument('-kkf', '--keepass-key-file', dest='kbdx_key_file', action='store', + help='Keepass key file for the exported file') export_parser.add_argument('--zip', dest='zip_archive', action='store_true', help='Create ZIP archive for file attachments. JSON only') export_parser.add_argument('--save-in-vault', dest='save_in_vault', action='store_true', From e49efb3bc24412c5d092a19b9159c62ac2482134 Mon Sep 17 00:00:00 2001 From: lthievenaz-keeper Date: Fri, 24 Jul 2026 16:41:38 +0100 Subject: [PATCH 2/3] Pass keepass-key-file arg through to exporter Passing the new keepass-key-file arg to exporter args. --- keepercommander/importer/imp_exp.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/keepercommander/importer/imp_exp.py b/keepercommander/importer/imp_exp.py index f36c9b068..912ab9ea4 100644 --- a/keepercommander/importer/imp_exp.py +++ b/keepercommander/importer/imp_exp.py @@ -431,6 +431,8 @@ def on_folder(base_folder): # type: (BaseFolderNode) -> None file_password = kwargs.get('file_password') if file_password: args['file_password'] = file_password + if kwargs.get('kbdx_key_file'): + args['kbdx_key_file'] = kwargs.get('kbdx_key_file') zip_archive = kwargs.get('zip_archive') is True if zip_archive: args['zip_archive'] = zip_archive From e886aec0f37f288d790f21c1eb34bec03b39b25c Mon Sep 17 00:00:00 2001 From: lthievenaz-keeper Date: Fri, 24 Jul 2026 16:44:33 +0100 Subject: [PATCH 3/3] Add support for Key Files in Keepass export Keepass export changes: - You can now pass the key file path as command arg keepass-key-file - If none set, you will be prompted for a file path (same as password) - If one set, the keepass exporter now handles Key File encryption of kbdx file. - Also since the password can be empty now, made it so that it will be null if none is set (otherwise you have to explicitly set a password in Keepass with empty value) --- keepercommander/importer/keepass/keepass.py | 24 ++++++++++----------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/keepercommander/importer/keepass/keepass.py b/keepercommander/importer/keepass/keepass.py index 4268ad67b..a31b9df1c 100644 --- a/keepercommander/importer/keepass/keepass.py +++ b/keepercommander/importer/keepass/keepass.py @@ -284,18 +284,15 @@ def to_keepass_value(keeper_value): # type: (any) -> str else: return XmlUtils.sanitize_xml_text(keeper_value) - def do_export(self, filename, records, file_password=None, **kwargs): - master_password = file_password - confirmed = True - while not master_password or not confirmed: - print('Choose password for your Keepass file') - master_password = getpass.getpass(prompt='...' + 'Keepass Password'.rjust(20) + ': ', stream=None) - print('\nRe-enter password for your Keepass file') - confirmation = getpass.getpass(prompt='...' + 'Keepass Password'.rjust(20) + ': ', stream=None) - confirmed = master_password == confirmation - retry_msg = 'The passwords you entered do not match.\nPlease try again.\n' - fail_msg = bcolors.FAIL + bcolors.BOLD + '\nALERT!\n' + retry_msg + bcolors.ENDC - not confirmed and print(fail_msg) + def do_export(self, filename, records, file_password=None, kbdx_key_file=None, **kwargs): + password = file_password or getpass.getpass(prompt='...' + 'Keepass Password'.rjust(20) + ': ', stream=None) or None + if not kbdx_key_file: + print('Press Enter if your Keepass file is not protected with a key file') + keyfile = kbdx_key_file or input('...' + 'Path to Key file'.rjust(20) + ': ') or None + if keyfile: + keyfile = os.path.expanduser(keyfile.strip("\"'")) + else: + keyfile = None sfs = [] # type: list[SharedFolder] rs = [] # type: list[Record] @@ -308,7 +305,8 @@ def do_export(self, filename, records, file_password=None, **kwargs): template_file = os.path.join(os.path.dirname(__file__), 'template.kdbx') with PyKeePass(template_file, password='111111') as kdb: - kdb.password = master_password + kdb.password = password + kdb.keyfile = keyfile root = kdb.root_group for r in rs: