Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); GitHub - devops35/WhatsApp-Crypt14-Crypt15-Decrypter: Decrypts WhatsApp .crypt14 / .crypt15 files. · GitHub
Skip to content

Repository files navigation

WhatsApp Crypt14-15 Backup Decrypter

Decrypts WhatsApp .crypt14 and .crypt15 files, given the key file or the 64-characters long key.
The key file is named "key" if the backup is crypt14 or
"encrypted_backup.key" if the backup is crypt15 (encrypted E2E backups).
The output result is either a SQLite database or a ZIP file (in case of wallpapers and stickers).
This is the only thing this script does. Those who are looking for a complete suite for WhatsApp forensics, check out whapa.

Quickstart

Just copy-paste this block into your terminal
(should be multi-platform - ignore errors during "activate" lines, as one is for Linux/macOS, one is for Windows (Batch) and one is for Windows PowerShell)

git clone https://github.com/ElDavoo/WhatsApp-Crypt14-Crypt15-Decrypter.git
cd WhatsApp-Crypt14-Crypt15-Decrypter
python -m venv venv
source venv/bin/activate
.\venv\Scripts\activate.bat
.\venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -r requirements.txt

Requirements

Remember to download the proto folder!

Python 3.7 or more recent

pycriptodomex or pycryptodome
javaobj-py3
protobuf 3.20 or more recent

... or just install the requirements.txt file

Use:

 python -m pip install -r requirements.txt

Or:

 python -m pip install pycryptodomex javaobj-py3 protobuf

Usage

usage: decrypt14_15.py [-h] [-f] [-nm] [-bs BUFFER_SIZE] [-ng] [-np]
[-ivo IV_OFFSET] [-do DATA_OFFSET] [-v]
[keyfile] [encrypted] [decrypted]
Decrypts WhatsApp backup files encrypted with Crypt14 or Crypt15
positional arguments:
keyfile The WhatsApp encrypted_backup key file or the hex
encoded key. Default: encrypted_backup.key
encrypted The encrypted crypt15 or crypt14 file. Default:
msgstore.db.crypt15
decrypted The decrypted output file. Default: msgstore.db
options:
-h, --help show this help message and exit
-f, --force Makes errors non fatal. Default: false
-nm, --no-mem Does not load files in RAM, stresses the disk more.
Default: load files into RAM
-bs BUFFER_SIZE, --buffer-size BUFFER_SIZE
How many bytes of data to process at a time. Implies
-nm. Default: 8192
-ng, --no-guess Does not try to guess the offsets, only protobuf
parsing.
-np, --no-protobuf Does not try to parse the protobuf message, only
offset guessing.
-ivo IV_OFFSET, --iv-offset IV_OFFSET
The default offset of the IV in the encrypted file.
Only relevant in offset guessing mode. Default: 8
-do DATA_OFFSET, --data-offset DATA_OFFSET
The default offset of the encrypted data in the
encrypted file. Only relevant in offset guessing mode.
Default: 122
-v, --verbose Prints all offsets and messages

Examples, with output

Crypt15

python ./decrypt14_15.py ./encrypted_backup.key ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

or

python ./decrypt14_15.py b1ef5568c31686d3339bcae4600c56cf7f0cb1ae982157060879828325257c11 ./msgstore.db.crypt15 ./msgstore.db
[I] Crypt15 key loaded
[I] Database header parsed
[I] Done

Crypt14

python ./decrypt14_15.py ./key ./msgstore.db.crypt14 ./msgstore.db
[I] Crypt12/14 key loaded
[I] Database header parsed
[I] Done

Crypt12 (unofficial)

python ./decrypt14_15.py ./key ./msgstore.db.crypt12 ./msgstore.db -np -ivo 51 -do 67 [I] Crypt12/14 key loaded
[I] WhatsApp version not found
[I] Offsets guessed (IV: 51, data: 67).
[I] Done

I had to use --force to decrypt

Please open an issue.

Not working / crash / etc

Please open an issue and attach:

  1. Output of the program (both with and without --force)
  2. Hexdump of keyfile
  3. Hexdump of first 512 bytes of encrypted DB

I will happily accept pull requests for the currently open issues. :)

Where do I get the key(file)?

On a rooted Android device, you can just copy /data/data/com.whatsapp/files/key (or /data/data/com.whatsapp/files/encrypted_backup.key if backups are crypt15).
If you enabled E2E backups, and you did not use a password (you have a copy of the 64-digit key, for example a screenshot), you can just transcribe and use it in lieu of the key file parameter.
There are other ways, but it is not in the scope of this project to tell you.
Issues asking for this will be closed as invalid.

Last tested version (don't expect this to be updated)

Stable: 2.22.15.74 Beta: 2.22.20.6

Stargazers over time

Star History Chart

Protobuf classes generation

You can replace the provided generated protobuf classes with your own.
In order to do that, download the protoc 21.0 from here. After that put protoc in the proto folder and run:
./protoc *.proto --python_out=.
We then need to manually patch the generated classes to fix import errors.
Open prefix_pb2.py and C14_cipher_pb2.py
Add proto. after any import keyword.
For example:
import C14_cipher_version_pb2 as C14__cipher__version__pb2
becomes
import proto.C14_cipher_version_pb2 as C14__cipher__version__pb2

Credits:

Original implementation for crypt12: TripCode
Some help at the beginning: DjEdu28
Actual crypt14/15 implementation with protobuf: ElDavoo

About

Decrypts WhatsApp .crypt14 / .crypt15 files.

Resources

Code of conduct

Contributing

Security policy

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages