3

I was trying to decrypt Whatsapp database file (msgstore.db.crypt) with java.

I found some python code and tried to do same thing with java. Probably its not that hard thing to do but I had some problems with handling decryption key.

But finally did it. So I wanted to share the code for people who need it.

Tom Zych
  • 13,329
  • 9
  • 36
  • 53
ali.turan
  • 535
  • 1
  • 6
  • 20

3 Answers3

3
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;


public class Crypto {

    public FileInputStream mIn;
    public FileOutputStream mOut;
    public Crypto(String fileIn, String fileOut) {
        try {
                mIn = new FileInputStream(new File(fileIn));
                mOut = new FileOutputStream(new File(fileOut));
                decryptAES(mIn, mOut);
        } catch (Exception e) {
                e.printStackTrace();
        }
    }

    public static void decryptAES(InputStream in, FileOutputStream out) throws Exception {
        final String string = "346a23652a46392b4d73257c67317e352e3372482177652c";
        byte[] hexAsBytes = DatatypeConverter.parseHexBinary(string);

        SecretKeySpec keySpec = new SecretKeySpec(hexAsBytes, "AES");
        Cipher cipher = Cipher.getInstance("AES"); 

        cipher.init(Cipher.DECRYPT_MODE, keySpec);

        in = new CipherInputStream(in, cipher);
        byte[] buffer = new byte[24]; 
        int bytesRead;
        while ((bytesRead = in.read(buffer)) != -1)
        {
            out.write(buffer, 0, bytesRead);
        }

    }


    public static void main(String[] args){    
        Crypto c = new Crypto("C:\\msgstore.db.crypt", "D:\\WhatsappDb");
        System.out.println("Decrypting Done");
    }
}
ali.turan
  • 535
  • 1
  • 6
  • 20
3

An updated answer for .crypt12 files:

These are compressed, and then encrypted using AES in GCM mode

Here is some python code showing how:

"""
Example how to decrypt whatsapp msgstore backups with extension .crypt12.
Author: Willem Hengeveld <itsme@xs4all.nl>
"""
from Crypto.Cipher import AES
import zlib
import sys

datafile = keyfile = None

if len(sys.argv)==1:
    print("Usage: decrypt12.py <keyfile> <msgstore.db.crypt12>")
    print("  the key file is commonly found in /data/data/com.whatsapp/files/key")
    print("  the crypt file is commonly found in the directory: /data/media/0/WhatsApp/Databases/")
    exit(1)

for arg in sys.argv[1:]:
    if arg.find('crypt12')>0:
        datafile = arg
    elif arg.find('key')>0:
        keyfile = arg
    else:
        print("unknown arg", arg)

with open(keyfile, "rb") as fh:
   keydata = fh.read()
key = keydata[126:]

with open(datafile, "rb") as fh:
   filedata = fh.read()
iv = filedata[51:67]

aes = AES.new(key, mode=AES.MODE_GCM, nonce=iv)

with open("msg-decrypted.db", "wb") as fh:
    fh.write(zlib.decompress(aes.decrypt(filedata[67:-20])))
Willem Hengeveld
  • 2,758
  • 23
  • 19
0

here is an pure java routine for .db.crypt12 without bouncycastle, but only JDK.

public class Crypt12 {
    public static void main(final String[] args) {
        final String c12File         = "1/msgstore.db.crypt12"; // input file
        final String decryptedDbFile = "1/msgstore.db";         // sqlite3 db output file
        final String keyFile         = "1/key";
        try {
            final byte[] key; try(FileInputStream s = new FileInputStream(keyFile)) { key = s.readAllBytes(); }
            final byte[] buf; try(FileInputStream s = new FileInputStream(c12File)) { buf = s.readAllBytes(); }
            if(!Arrays.equals(key, 27, 78, buf, 0, 51)) { System.out.println("Wrong Key-File"); return; }
            final int available = buf.length - 67  - 20; // 67 Byte Header + 20 byte footer
            final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
            final GCMParameterSpec iv = new GCMParameterSpec(128, buf, 51, 16);
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, 126, 32, "AES"), iv);
            final int zipLen = cipher.doFinal(buf, 67, available, buf, 0);
            final Inflater unzip = new Inflater(false);
            try(FileOutputStream s = new FileOutputStream(decryptedDbFile)) {
                unzip.setInput(buf, 0, zipLen);
                final byte[] b = new byte[1024];
                while(!unzip.needsInput()) {
                    final int l = unzip.inflate(b, 0, b.length);
                    if(l > 0) s.write(b, 0, l);
                }
            }
        } catch (final Exception e) {
            e.printStackTrace(System.out);
        }
    }
}
SkateScout
  • 815
  • 14
  • 24