From 48f667d02b96e64a9432adda94315b2731472435 Mon Sep 17 00:00:00 2001 From: KnugiHK <24708955+KnugiHK@users.noreply.github.com> Date: Mon, 5 Sep 2022 12:16:07 +0800 Subject: [PATCH] Implement exporting 64-digit crypt15 encryption key https://github.com/KnugiHK/Whatsapp-Chat-Exporter/issues/20 --- Whatsapp_Chat_Exporter/__main__.py | 9 ++++++++- Whatsapp_Chat_Exporter/extract.py | 11 +++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/Whatsapp_Chat_Exporter/__main__.py b/Whatsapp_Chat_Exporter/__main__.py index d449a91..2ccb4a8 100644 --- a/Whatsapp_Chat_Exporter/__main__.py +++ b/Whatsapp_Chat_Exporter/__main__.py @@ -85,6 +85,13 @@ def main(): default=False, action='store_true', help="Embed media into HTML file") + parser.add_option( + "-s", + "--showkey", + dest="showkey", + default=False, + action='store_true', + help="Show the HEX key used to decrypt the database") (options, args) = parser.parse_args() if options.android and options.iphone: @@ -121,7 +128,7 @@ def main(): elif all(char in string.hexdigits for char in options.key): key = bytes.fromhex(options.key) db = open(options.backup, "rb").read() - error = extract.decrypt_backup(db, key, msg_db, crypt) + error = extract.decrypt_backup(db, key, msg_db, crypt, options.showkey) if error != 0: if error == 1: print("Dependencies of decrypt_backup and/or extract_encrypted_key" diff --git a/Whatsapp_Chat_Exporter/extract.py b/Whatsapp_Chat_Exporter/extract.py index f2aebf1..f13eecf 100644 --- a/Whatsapp_Chat_Exporter/extract.py +++ b/Whatsapp_Chat_Exporter/extract.py @@ -71,7 +71,7 @@ def _generate_hmac_of_hmac(key_stream): b"backup encryption\x01", sha256 ) - return key.digest() + return key.digest(), key_stream def _extract_encrypted_key(keyfile): @@ -82,7 +82,7 @@ def _extract_encrypted_key(keyfile): return _generate_hmac_of_hmac(key_stream) -def decrypt_backup(database, key, output, crypt=Crypt.CRYPT14): +def decrypt_backup(database, key, output, crypt=Crypt.CRYPT14, show_crypt15=False): if not support_backup: return 1 if isinstance(key, io.IOBase): @@ -119,9 +119,12 @@ def decrypt_backup(database, key, output, crypt=Crypt.CRYPT14): if crypt == Crypt.CRYPT15: if len(key) == 32: - main_key = _generate_hmac_of_hmac(key) + main_key, hex_key = _generate_hmac_of_hmac(key) else: - main_key = _extract_encrypted_key(key) + main_key, hex_key = _extract_encrypted_key(key) + if show_crypt15: + hex_key = [hex_key.hex()[c:c+4] for c in range(0, len(hex_key.hex()), 4)] + print("The HEX key of the crypt15 backup is: " + ' '.join(hex_key)) else: main_key = key[126:] decompressed = False