如何解密Whatsapp数据库文件?

时间:2014-03-11 00:58:19

标签: java database encryption whatsapp

我试图用java解密Whatsapp数据库文件(msgstore.db.crypt)。

我发现了一些python代码并试图用java做同样的事情。可能它不是那么难,但我在处理解密密钥时遇到了一些问题。

但终于做到了。所以我想为需要它的人分享代码。

3 个答案:

答案 0 :(得分:4)

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");
    }
}

答案 1 :(得分:2)

.crypt12个文件的更新答案:

这些是压缩的,然后在GCM模式下使用AES加密

这是一些python代码,展示了如何:

"""
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])))

答案 2 :(得分:0)

这是.db.crypt12的纯Java例程,没有bouncycastle,但只有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);
        }
    }
}