From 0a2bc9c49b13c0fc6b9194c4a1cebfaae5f90cce Mon Sep 17 00:00:00 2001 From: Ayrris Aunario Date: Thu, 18 Jul 2024 10:26:12 -0500 Subject: [PATCH] `security-audit report/sync` improvements/fixes: 1) fix for decryption of insufficiently-padded security-data 2) support for non-interactive summary score resetting (no confirmation prompt) + minimal screen output (no security-audit report run on sync done) --- keepercommander/commands/security_audit.py | 12 ++++++++---- keepercommander/crypto.py | 8 +++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/keepercommander/commands/security_audit.py b/keepercommander/commands/security_audit.py index e0f014e4e..f49513f2a 100644 --- a/keepercommander/commands/security_audit.py +++ b/keepercommander/commands/security_audit.py @@ -59,6 +59,9 @@ def register_command_info(aliases, command_info): sync_email_help = 'email of target vault\'s owner. Accepts multiple values. Supports the following pseudo-users: @all' sync_parser.add_argument('email', type=str, nargs='+', help=sync_email_help) +sync_verbose_help = 'run and show the latest security-audit report immediately after sync' +sync_parser.add_argument('-v', '--verbose', action='store_true', help=sync_verbose_help) +sync_parser.add_argument('-f', '--force', action='store_true', help='do sync non-interactively') sync_parser.error = raise_parse_exception sync_parser.exit = suppress_exit @@ -343,7 +346,7 @@ def decrypt_security_data(sec_data, k): # type: (bytes, RSAPrivateKey) -> Dict[ decrypted = None if sec_data: try: - decrypted = crypto.decrypt_rsa(sec_data, k) + decrypted = crypto.decrypt_rsa(sec_data, k, pad_plaintext=True) except Exception as e: error = f'Decrypt fail (incremental data): {e}' self.get_error_report_builder().update_report_data(error) @@ -529,11 +532,12 @@ def confirm_sync(): f' scores.' confirm_txt = f'{hard_sync_desc}\n\n{confirm_txt}' prompt_txt = f'{prompt_title}{sync_targets}\n\n{confirm_txt}' - if confirm(prompt_txt): + if kwargs.get('force') or confirm(prompt_txt): api.communicate_rest(params, rq, 'enterprise/clear_security_data') # Re-calculate and save new security scores - sar_cmd = SecurityAuditReportCommand() - return sar_cmd.execute(params, save=True) + if kwargs.get('verbose'): + sar_cmd = SecurityAuditReportCommand() + return sar_cmd.execute(params, save=True) else: logging.info(f'Security-data ({sync_type}) sync aborted') diff --git a/keepercommander/crypto.py b/keepercommander/crypto.py index 35b3ef909..0bd22f68d 100644 --- a/keepercommander/crypto.py +++ b/keepercommander/crypto.py @@ -128,7 +128,13 @@ def encrypt_rsa(data, rsa_key): return rsa_key.encrypt(data, PKCS1v15()) -def decrypt_rsa(data, rsa_key): +def decrypt_rsa(data, rsa_key, pad_plaintext=False): + size_diff = (rsa_key.key_size >> 3) - len(data) + if pad_plaintext and size_diff: + pad_bytes = bytes(size_diff) + pad_bytearray = bytearray([b for b in pad_bytes]) + data_bytearray = bytearray([b for b in data]) + data = bytes(pad_bytearray + data_bytearray) return rsa_key.decrypt(data, PKCS1v15())