[GH-ISSUE #20] Support .mcrypt1 files #18

Open
opened 2026-03-02 03:59:19 +03:00 by kerem · 21 comments
Owner

Originally created by @ElDavoo on GitHub (Apr 13, 2022).
Original GitHub issue: https://github.com/ElDavoo/wa-crypt-tools/issues/20

Originally assigned to: @ElDavoo on GitHub.

This will probably be complicated and result in a writing of a google drive downloader, as metadata needs to be decrypted and it will probably a lot of stuff and logic to write.

.mcrypt1 files are encrypted media files uploaded in the cloud (google drive) while using E2E encrypted backups.

I can't allocate time to this task, so for a few months there will be no progress. I'll be happy to accept external contributions. There should be no forward secrecy, so you might be able to start downloading encrypted media using existing downloaders and decrypt them when the tool will be ready.

Originally created by @ElDavoo on GitHub (Apr 13, 2022). Original GitHub issue: https://github.com/ElDavoo/wa-crypt-tools/issues/20 Originally assigned to: @ElDavoo on GitHub. This will probably be complicated and result in a writing of a google drive downloader, as metadata needs to be decrypted and it will probably a lot of stuff and logic to write. .mcrypt1 files are encrypted media files uploaded in the cloud (google drive) while using E2E encrypted backups. **I can't allocate time to this task, so for a few months there will be no progress.** I'll be happy to accept external contributions. There should be no forward secrecy, so you might be able to start downloading encrypted media using existing downloaders and decrypt them when the tool will be ready.
Author
Owner

@ElDavoo commented on GitHub (Mar 3, 2023):

Might this project help? https://github.com/robertdavidgraham/whats-dec

<!-- gh-comment-id:1454209603 --> @ElDavoo commented on GitHub (Mar 3, 2023): Might this project help? https://github.com/robertdavidgraham/whats-dec
Author
Owner

@ElDavoo commented on GitHub (Aug 27, 2023):

Metadata decryption function added

<!-- gh-comment-id:1694605731 --> @ElDavoo commented on GitHub (Aug 27, 2023): Metadata decryption function added
Author
Owner

@bone6000 commented on GitHub (Dec 14, 2023):

hello @ElDavoo,

can you confirm if there is a way to decrypt .mcrypt1 files?

I've overwritten my drive backup by mistake but I have all my photos/videos .mcrypt1 files locally in the phone, so I would like to restore them.

Regards,

<!-- gh-comment-id:1855965788 --> @bone6000 commented on GitHub (Dec 14, 2023): hello @ElDavoo, can you confirm if there is a way to decrypt .mcrypt1 files? I've overwritten my drive backup by mistake but I have all my photos/videos .mcrypt1 files locally in the phone, so I would like to restore them. Regards,
Author
Owner

@ElDavoo commented on GitHub (Dec 24, 2023):

can you confirm if there is a way to decrypt .mcrypt1 files?

yep

<!-- gh-comment-id:1868505308 --> @ElDavoo commented on GitHub (Dec 24, 2023): > can you confirm if there is a way to decrypt .mcrypt1 files? yep
Author
Owner

@bone6000 commented on GitHub (Dec 24, 2023):

Can you please tell me how to do it?

<!-- gh-comment-id:1868508189 --> @bone6000 commented on GitHub (Dec 24, 2023): Can you please tell me how to do it?
Author
Owner

@ElDavoo commented on GitHub (Dec 24, 2023):

work in progress, i will probably do it during the vacations

<!-- gh-comment-id:1868532239 --> @ElDavoo commented on GitHub (Dec 24, 2023): work in progress, i will probably do it during the vacations
Author
Owner

@ShubhSrivastava1326 commented on GitHub (Mar 21, 2024):

Did you do it? I forgot my E2E encryption 64-digit code but i have downloaded the backup from google drive on my laptop and want to decrypt it. Please help, I cant lose all my messages.

<!-- gh-comment-id:2011854890 --> @ShubhSrivastava1326 commented on GitHub (Mar 21, 2024): Did you do it? I forgot my E2E encryption 64-digit code but i have downloaded the backup from google drive on my laptop and want to decrypt it. Please help, I cant lose all my messages.
Author
Owner

@bone6000 commented on GitHub (Apr 12, 2024):

I'm also still waiting with my encrypted .mcrypt1 photos and videos in my laptop. LOL

<!-- gh-comment-id:2051625078 --> @bone6000 commented on GitHub (Apr 12, 2024): I'm also still waiting with my encrypted .mcrypt1 photos and videos in my laptop. LOL
Author
Owner

@ElDavoo commented on GitHub (Apr 12, 2024):

I'm also still waiting with my encrypted .mcrypt1 photos and videos in my laptop. LOL

Sorry, but .mcrypt1 by themselves are not decryptable. Additional metadata from Google drive is needed.

The latest version on master branch of whapa downloads this metadata in the form of .mcrypt1-metadata files.

<!-- gh-comment-id:2051681865 --> @ElDavoo commented on GitHub (Apr 12, 2024): > I'm also still waiting with my encrypted .mcrypt1 photos and videos in my laptop. LOL Sorry, but .mcrypt1 by themselves are not decryptable. Additional metadata from Google drive is needed. The latest version on master branch of whapa downloads this metadata in the form of .mcrypt1-metadata files.
Author
Owner

@ElDavoo commented on GitHub (Apr 12, 2024):

I'm also still waiting with my encrypted .mcrypt1 photos and videos in my laptop. LOL

Sorry, but .mcrypt1 by themselves are not decryptable. Additional metadata from Google drive is needed.

The latest version on master branch of whapa downloads this metadata in the form of .mcrypt1-metadata files.

<!-- gh-comment-id:2051682092 --> @ElDavoo commented on GitHub (Apr 12, 2024): > I'm also still waiting with my encrypted .mcrypt1 photos and videos in my laptop. LOL Sorry, but .mcrypt1 by themselves are not decryptable. Additional metadata from Google drive is needed. The latest version on master branch of whapa downloads this metadata in the form of .mcrypt1-metadata files.
Author
Owner

@bone6000 commented on GitHub (Apr 12, 2024):

Im not sure if I have that metadata files in my local drive, I have to check... Anyway, is this function going to be implemented?
If I manage to get that metadata files can you tell me how to decrypt it?
Thanks

<!-- gh-comment-id:2051690270 --> @bone6000 commented on GitHub (Apr 12, 2024): Im not sure if I have that metadata files in my local drive, I have to check... Anyway, is this function going to be implemented? If I manage to get that metadata files can you tell me how to decrypt it? Thanks
Author
Owner

@giacomoferretti commented on GitHub (Nov 7, 2024):

Sorry, but .mcrypt1 by themselves are not decryptable. Additional metadata from Google drive is needed.

The latest version on master branch of whapa downloads this metadata in the form of .mcrypt1-metadata files.

This is not accurate. Yes, if you want the correct filename and filepath, you need the .mcrypt1-metadata files, but if you only want to decrypt the .mcrypt1 file, you only need the backup key and the filename of the .mcrypt1 file (assuming the filename is correct).

You can check out the complete code in the following repository: github.com/giacomoferretti/whatsapp-backup-downloader-decryptor@b6178235fe/wabdd/commands/decrypt.py (L31-L55).

Here’s a snippet for decrypting the .mcrypt1 file:

import pathlib

from Cryptodome.Cipher import AES
from wa_crypt_tools.lib.key.key15 import Key15
from wa_crypt_tools.lib.utils import encryptionloop

# This is the backup key
BACKUP_KEY = Key15(keyarray=bytes.fromhex("0000000000000000000000000000000000000000000000000000000000000000"))
EXAMPLE_FILE = "0000000000000000000000000000000000000000000000000000000000000000.mcrypt1"

# ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA -----

# Read metadata file
with open(EXAMPLE_FILE + "-metadata") as f:
    metadata = mcrypt1_metadata_decrypt(key=BACKUP_KEY, encoded=f.read())

# Prepare output filepath
output_file = output / pathlib.Path(metadata["name"])
output_file.parent.mkdir(parents=True, exist_ok=True)

# ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA -----

# Get filename without `.mcrypt1` extension and convert to bytes
decryption_hash = bytes.fromhex(pathlib.Path(EXAMPLE_FILE).with_suffix("").name)
decryption_data = encryptionloop(
    first_iteration_data=BACKUP_KEY.get_root(),
    message=decryption_hash,
    output_bytes=48,
)

# Prepare AES
aes_key = decryption_data[:32]
aes_iv = decryption_data[32:48]
cipher = AES.new(aes_key, AES.MODE_GCM, aes_iv)

# Read cyphertext
with open(file, "rb") as f:
    encrypted_data = f.read()

# Decrypt and write
with open(output_file, "wb") as f:
    f.write(cipher.decrypt(encrypted_data))
<!-- gh-comment-id:2461933598 --> @giacomoferretti commented on GitHub (Nov 7, 2024): > Sorry, but .mcrypt1 by themselves are not decryptable. Additional metadata from Google drive is needed. > > The latest version on master branch of whapa downloads this metadata in the form of .mcrypt1-metadata files. This is not accurate. Yes, if you want the correct filename and filepath, you need the `.mcrypt1-metadata` files, but if you only want to decrypt the `.mcrypt1` file, you only need the backup key and the filename of the `.mcrypt1` file (assuming the filename is correct). You can check out the complete code in the following repository: https://github.com/giacomoferretti/whatsapp-backup-downloader-decryptor/blob/b6178235fed497d0d5b9e49293a3d9e2c219c10a/wabdd/commands/decrypt.py#L31-L55. Here’s a snippet for decrypting the `.mcrypt1` file: ```python import pathlib from Cryptodome.Cipher import AES from wa_crypt_tools.lib.key.key15 import Key15 from wa_crypt_tools.lib.utils import encryptionloop # This is the backup key BACKUP_KEY = Key15(keyarray=bytes.fromhex("0000000000000000000000000000000000000000000000000000000000000000")) EXAMPLE_FILE = "0000000000000000000000000000000000000000000000000000000000000000.mcrypt1" # ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA ----- # Read metadata file with open(EXAMPLE_FILE + "-metadata") as f: metadata = mcrypt1_metadata_decrypt(key=BACKUP_KEY, encoded=f.read()) # Prepare output filepath output_file = output / pathlib.Path(metadata["name"]) output_file.parent.mkdir(parents=True, exist_ok=True) # ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA ----- # Get filename without `.mcrypt1` extension and convert to bytes decryption_hash = bytes.fromhex(pathlib.Path(EXAMPLE_FILE).with_suffix("").name) decryption_data = encryptionloop( first_iteration_data=BACKUP_KEY.get_root(), message=decryption_hash, output_bytes=48, ) # Prepare AES aes_key = decryption_data[:32] aes_iv = decryption_data[32:48] cipher = AES.new(aes_key, AES.MODE_GCM, aes_iv) # Read cyphertext with open(file, "rb") as f: encrypted_data = f.read() # Decrypt and write with open(output_file, "wb") as f: f.write(cipher.decrypt(encrypted_data)) ```
Author
Owner

@ElDavoo commented on GitHub (Nov 8, 2024):

if you only want to decrypt the .mcrypt1 file, you only need the backup key and the filename of the .mcrypt1 file (assuming the filename is correct).

And where exactly do you take the filename if not from the metadata section?
If you cleaned your local storage there is no other option to know it (well, maybe it can be bruteforced in some situations... I need to investigate the feasibility of the approach).

edit: i shouldn't do this stuff when i'm tired... i remembered more clearly now.
While accurate, it is not user friendly to decrypt data without knowing the filename. The user must identify the file by hand.
If you have to restore a normal backup, it will have hundreds of files, so it is essential to get the directory tree (and the files) back to original, otherwise you won't see them in whatsapp after a restore.
So yeah you can decrypt without filename but it's not going to be useful in all scenarios.

Here’s a snippet for decrypting the .mcrypt1 file:

Cool code! Keep in mind that I will probably overhaul the mcrypt functions (they're just a POC).
Your code is definitely useful in getting the auth token from google (which i had problems doing).

<!-- gh-comment-id:2465808790 --> @ElDavoo commented on GitHub (Nov 8, 2024): > if you only want to decrypt the `.mcrypt1` file, you only need the backup key and the filename of the `.mcrypt1` file (assuming the filename is correct). And where exactly do you take the filename if not from the metadata section? If you cleaned your local storage there is no other option to know it (well, maybe it can be bruteforced in some situations... I need to investigate the feasibility of the approach). edit: i shouldn't do this stuff when i'm tired... i remembered more clearly now. While accurate, it is not user friendly to decrypt data without knowing the filename. The user must identify the file by hand. If you have to restore a normal backup, it will have hundreds of files, so it is essential to get the directory tree (and the files) back to original, otherwise you won't see them in whatsapp after a restore. So yeah you can decrypt without filename but it's not going to be useful in all scenarios. > Here’s a snippet for decrypting the `.mcrypt1` file: Cool code! Keep in mind that I will probably overhaul the mcrypt functions (they're just a POC). Your code is definitely useful in getting the auth token from google (which i had problems doing).
Author
Owner

@giacomoferretti commented on GitHub (Nov 9, 2024):

If you have to restore a normal backup, it will have hundreds of files, so it is essential to get the directory tree (and the files) back to original, otherwise you won't see them in whatsapp after a restore.
So yeah you can decrypt without filename but it's not going to be useful in all scenarios.

I totally agree with you. The fact that you can decrypt without metadata is more for extreme use if you want to at least recover the data, kind of like various file recovery software does (for example, if the backup was downloaded with software that doesn't save metadata). For the average user this is not useful.

Cool code! Keep in mind that I will probably overhaul the mcrypt functions (they're just a POC).

I mean, the only difference between .crypt15 and .mcrypt1 is this:

.crypt15 github.com/ElDavoo/wa-crypt-tools@cf490fc599/src/wa_crypt_tools/lib/key/key15.py (L63-L66)

.mcrypt1

encryptionloop(
    first_iteration_data=key,
    message=decryption_hash, # The filename in hex as bytes
    output_bytes=48, # KEY + IV
)
<!-- gh-comment-id:2466307564 --> @giacomoferretti commented on GitHub (Nov 9, 2024): > If you have to restore a normal backup, it will have hundreds of files, so it is essential to get the directory tree (and the files) back to original, otherwise you won't see them in whatsapp after a restore. > So yeah you can decrypt without filename but it's not going to be useful in all scenarios. I totally agree with you. The fact that you can decrypt without metadata is more for extreme use if you want to at least recover the data, kind of like various file recovery software does (for example, if the backup was downloaded with software that doesn't save metadata). For the average user this is not useful. > Cool code! Keep in mind that I will probably overhaul the mcrypt functions (they're just a POC). I mean, the only difference between `.crypt15` and `.mcrypt1` is this: `.crypt15` https://github.com/ElDavoo/wa-crypt-tools/blob/cf490fc599a08563d040ab94c96678a9ae1a4f48/src/wa_crypt_tools/lib/key/key15.py#L63-L66 <!-- ```python encryptionloop( first_iteration_data=key, message=b'backup encryption', output_bytes=32 ) ``` --> `.mcrypt1` ```python encryptionloop( first_iteration_data=key, message=decryption_hash, # The filename in hex as bytes output_bytes=48, # KEY + IV ) ````
Author
Owner

@bone6000 commented on GitHub (Nov 15, 2024):

How can I get the "BACKUP_KEY" to put in the snippet?

I have access to my old phone (rooted) and I can see in "/data/com.whatsapp/files" some files like:

key
encrypted_backup.key
backup_token
password_data.key

Is any of that file? All of them seems like garbage when opening in notepad++

<!-- gh-comment-id:2478509277 --> @bone6000 commented on GitHub (Nov 15, 2024): How can I get the "BACKUP_KEY" to put in the snippet? I have access to my old phone (rooted) and I can see in "/data/com.whatsapp/files" some files like: key encrypted_backup.key backup_token password_data.key Is any of that file? All of them seems like garbage when opening in notepad++
Author
Owner

@bone6000 commented on GitHub (Mar 24, 2025):

can somebody confirm if there is any advance with this?

<!-- gh-comment-id:2747722365 --> @bone6000 commented on GitHub (Mar 24, 2025): can somebody confirm if there is any advance with this?
Author
Owner

@giacomoferretti commented on GitHub (Mar 24, 2025):

How can I get the "BACKUP_KEY" to put in the snippet?

I have access to my old phone (rooted) and I can see in "/data/com.whatsapp/files" some files like:

key encrypted_backup.key backup_token password_data.key

Is any of that file? All of them seems like garbage when opening in notepad++

Put the hex value of encrypted_backup.key

<!-- gh-comment-id:2747770875 --> @giacomoferretti commented on GitHub (Mar 24, 2025): > How can I get the "BACKUP_KEY" to put in the snippet? > > I have access to my old phone (rooted) and I can see in "/data/com.whatsapp/files" some files like: > > key encrypted_backup.key backup_token password_data.key > > Is any of that file? All of them seems like garbage when opening in notepad++ Put the hex value of `encrypted_backup.key`
Author
Owner

@bone6000 commented on GitHub (Mar 24, 2025):

Hello Giacomo,

The content of "encrypted_backup.key" is this like garbaje stuff.

Image

I can open the file with HxD Hex Editor but not sure which hex values should I put in the snippet... can you tell me exactly which key should i paste in the code?

Regards,

<!-- gh-comment-id:2747925742 --> @bone6000 commented on GitHub (Mar 24, 2025): Hello Giacomo, The content of "encrypted_backup.key" is this like garbaje stuff. ![Image](https://github.com/user-attachments/assets/8f2a1658-b745-4e1e-8c90-2afe24ac12d0) I can open the file with HxD Hex Editor but not sure which hex values should I put in the snippet... can you tell me exactly which key should i paste in the code? Regards,
Author
Owner

@giacomoferretti commented on GitHub (Mar 24, 2025):

Sorry, I didn't give enough details. The encrypted_backup.key is your key. The entire content is the key, just copy the content as an HEX string and paste it in the snippet.

<!-- gh-comment-id:2747952737 --> @giacomoferretti commented on GitHub (Mar 24, 2025): Sorry, I didn't give enough details. The `encrypted_backup.key` is your key. The entire content is the key, just copy the content as an HEX string and paste it in the snippet.
Author
Owner

@bone6000 commented on GitHub (Mar 24, 2025):

I've used this script to convert the content of the encrypted_key to hex:

def file_to_hex(filename):
    with open(filename, 'rb') as file:
        content = file.read()
        hex_content = content.hex()  # Convert to hex
        return hex_content

file_path = 'encrypted_backup.key'  # Replace with your file path
hex_representation = file_to_hex(file_path)
print(hex_representation)

After that I've pasted the hex output to your snippet code like this:

import pathlib

from Cryptodome.Cipher import AES
from wa_crypt_tools.lib.key.key15 import Key15
from wa_crypt_tools.lib.utils import encryptionloop

# This is the backup key
BACKUP_KEY = Key15(keyarray=bytes.fromhex("ACED0005757200025B42ACF317F8060854E0020000787000000020C222A14327B202A57B5507093C18CF01F14C74B8A7882CDE35BEEA3775F221B7"))
EXAMPLE_FILE = "00B329C04EDBA39499DFDA241711CB6DDAA734994C157AB3E1D5ED9BBB4276E1.mcrypt1"

# ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA -----

# Read metadata file
with open(EXAMPLE_FILE + "-metadata") as f:
    metadata = mcrypt1_metadata_decrypt(key=BACKUP_KEY, encoded=f.read())

# Prepare output filepath
output_file = output / pathlib.Path(metadata["name"])
output_file.parent.mkdir(parents=True, exist_ok=True)

# ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA -----

# Get filename without `.mcrypt1` extension and convert to bytes
decryption_hash = bytes.fromhex(pathlib.Path(EXAMPLE_FILE).with_suffix("").name)
decryption_data = encryptionloop(
    first_iteration_data=BACKUP_KEY.get_root(),
    message=decryption_hash,
    output_bytes=48,
)

# Prepare AES
aes_key = decryption_data[:32]
aes_iv = decryption_data[32:48]
cipher = AES.new(aes_key, AES.MODE_GCM, aes_iv)

# Read cyphertext
with open(file, "rb") as f:
    encrypted_data = f.read()

# Decrypt and write
with open(output_file, "wb") as f:
    f.write(cipher.decrypt(encrypted_data))

After executing the snippet a file was created. It should be a MP4 file, but I can't open it (the file header does not match any know file extension), so or the encrypted_key to hex is not valid or something is wrong elsewhere. Any idea how to troubleshoot this?

<!-- gh-comment-id:2748183238 --> @bone6000 commented on GitHub (Mar 24, 2025): I've used this script to convert the content of the encrypted_key to hex: ``` def file_to_hex(filename): with open(filename, 'rb') as file: content = file.read() hex_content = content.hex() # Convert to hex return hex_content file_path = 'encrypted_backup.key' # Replace with your file path hex_representation = file_to_hex(file_path) print(hex_representation) ``` After that I've pasted the hex output to your snippet code like this: ``` import pathlib from Cryptodome.Cipher import AES from wa_crypt_tools.lib.key.key15 import Key15 from wa_crypt_tools.lib.utils import encryptionloop # This is the backup key BACKUP_KEY = Key15(keyarray=bytes.fromhex("ACED0005757200025B42ACF317F8060854E0020000787000000020C222A14327B202A57B5507093C18CF01F14C74B8A7882CDE35BEEA3775F221B7")) EXAMPLE_FILE = "00B329C04EDBA39499DFDA241711CB6DDAA734994C157AB3E1D5ED9BBB4276E1.mcrypt1" # ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA ----- # Read metadata file with open(EXAMPLE_FILE + "-metadata") as f: metadata = mcrypt1_metadata_decrypt(key=BACKUP_KEY, encoded=f.read()) # Prepare output filepath output_file = output / pathlib.Path(metadata["name"]) output_file.parent.mkdir(parents=True, exist_ok=True) # ----- THIS SECTION IS OPTIONAL IF YOU ONLY WANT TO DECRYPT DATA ----- # Get filename without `.mcrypt1` extension and convert to bytes decryption_hash = bytes.fromhex(pathlib.Path(EXAMPLE_FILE).with_suffix("").name) decryption_data = encryptionloop( first_iteration_data=BACKUP_KEY.get_root(), message=decryption_hash, output_bytes=48, ) # Prepare AES aes_key = decryption_data[:32] aes_iv = decryption_data[32:48] cipher = AES.new(aes_key, AES.MODE_GCM, aes_iv) # Read cyphertext with open(file, "rb") as f: encrypted_data = f.read() # Decrypt and write with open(output_file, "wb") as f: f.write(cipher.decrypt(encrypted_data)) ``` After executing the snippet a file was created. It should be a MP4 file, but I can't open it (the file header does not match any know file extension), so or the encrypted_key to hex is not valid or something is wrong elsewhere. Any idea how to troubleshoot this?
Author
Owner

@giacomoferretti commented on GitHub (Mar 26, 2025):

I'm sorry, I was wrong. encrypted_backup.key is a Java serialized object, so you'll need to get the last 32 bytes for the Key15.

with open("encrypted_backup.key", "rb") as f:
    print(f.read()[-32:].hex())
<!-- gh-comment-id:2753015294 --> @giacomoferretti commented on GitHub (Mar 26, 2025): I'm sorry, I was wrong. `encrypted_backup.key` is a Java serialized object, so you'll need to get the last 32 bytes for the Key15. ```python with open("encrypted_backup.key", "rb") as f: print(f.read()[-32:].hex()) ```
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/wa-crypt-tools#18
No description provided.