Decrypt WhatsAPP's Crypt12 Databases

Decrypt WhatsApp's msgstore.db.crypt12 chat database files with Python 3. This script is a Python 3, and requires pycrypto and pycryptodome modules.

You'll need the database file, which is called msgstore.db.crypt12, the decryption key, called simply key and the script below.


With Python 3 installed, install the required modules:

pip3 install pycrypto
pip3 install pycryptodome

Put the .crypt12 and the key files in the same folder and run the script, like this:

 MTeam7 [~] $ python3 key msgstore.db.crypt12
Decryption of crypt12 file was successful.

 MTeam7 [~] $ ls msgstore.db
504K -rw-r--r-- 1 aegon staff 504K Aug 16 11:56 msgstore.db

The database file format is SQLite. We can dump into a file like this:

  MTeam7 [~] $ sqlite3 msgstore.db
SQLite version 3.16.0 2016-11-04 19:09:39
Enter ".help" for usage hints.
sqlite> .output plaintext.sql
sqlite> .dump
sqlite> .quit

  MTeam7 [~] $ head -n 3 plaintext.sql
PRAGMA foreign_keys=OFF;
CREATE TABLE messages (_id INTEGER PRIMARY KEY AUTOINCREMENT, key_remote_jid TEXT NOT NULL, key_from_me INTEGER, key_id TEXT NOT NULL, status INTEGER, needs_push INTEGER, data TEXT, timestamp INTEGER, media_url TEXT, media_mime_type TEXT, media_wa_type TEXT, media_size INTEGER, media_name TEXT, media_caption TEXT, media_hash TEXT, media_duration INTEGER, origin INTEGER, latitude REAL, longitude REAL, thumb_image TEXT, remote_resource TEXT, received_timestamp INTEGER, send_timestamp INTEGER, receipt_server_timestamp INTEGER, receipt_device_timestamp INTEGER, read_device_timestamp INTEGER, played_device_timestamp INTEGER, raw_data BLOB, recipient_count INTEGER, participant_hash TEXT, starred INTEGER, quoted_row_id INTEGER, mentioned_jids TEXT, multicast_id TEXT, edit_version INTEGER, media_enc_hash TEXT, payment_transaction_id TEXT, forwarded INTEGER, preview_type INTEGER, send_count INTEGER);


Don't forget to edit Python's path in the shebang (the first line of the script) with the correct Python 3 binary path.

Copy the script below or download it here:


from Crypto.Cipher import AES
import os
import sys
import zlib

def keyfile(kf):
    global t1, key
    if os.path.isfile(kf) == False:
        quit('The specified input key file does not exist.')
    elif os.path.getsize(kf) != 158:
        quit('The specified input key file is invalid.')
    with open(kf, 'rb') as keyfile:
        t1 =
        key =
    return True

def decrypt12(cf, of):
    global t2, iv
    if os.path.isfile(cf) == False:
        quit('The specified input crypt12 file does not exist.')
    tf = cf+'.tmp'
    with open(cf, 'rb') as crypt12:
        t2 =
        if t1 != t2:
            quit('Key file mismatch or crypt12 file is corrupt.')
        iv =
        primer(tf, crypt12, 20)
    cipher =, AES.MODE_GCM, iv)
    sqlite = zlib.decompress(cipher.decrypt(open(tf, 'rb').read()))
    with open(of, 'wb') as msgstore:
    return True

def primer(tf, crypt12, sb):
    with open(tf, 'wb') as header:
    with open(tf, 'rb+') as footer:, os.SEEK_END)

def validate(ms):
    with open(ms, 'rb') as msgstore:
        if'ascii').lower() != 'sqlite':
            msg = 'Decryption of crypt12 file has failed.'
            msg = 'Decryption of crypt12 file was successful.'

def main():
    if len(sys.argv) > 2 and len(sys.argv) < 5:
        if len(sys.argv) == 3:
            outfile = 'msgstore.db'
            outfile = sys.argv[3]
        if keyfile(sys.argv[1]) and decrypt12(sys.argv[2], outfile):
        print('\nWhatsApp Crypt12 Database Decrypter' + '\n')
        print('\tUsage: python '+str(sys.argv[0])+' key msgstore.db.crypt12 msgstore.db\n')

if __name__ == "__main__":
{{ message }}

{{ 'Comments are closed.' | trans }}