【问题标题】:How to decrypt Whatsapp Database File?如何解密 Whatsapp 数据库文件?
【发布时间】:2014-04-14 09:32:09
【问题描述】:

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

我找到了一些 python 代码并尝试用 java 做同样的事情。可能这并不难,但我在处理解密密钥时遇到了一些问题。

但最终还是做到了。所以我想把代码分享给有需要的人。

【问题讨论】:

标签: java database encryption whatsapp


【解决方案1】:

这是一个用于 .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);
        }
    }
}

【讨论】:

    【解决方案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])))
    

    【讨论】:

    • 你知道如何加密(即创建一个 .crypt12 文件)吗?加密文件中的页眉和页脚是什么!?
    【解决方案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");
        }
    }
    

    【讨论】:

    • 为什么不将 keySpec 传递给解密例程?这样,您只需实例化一次即可解密多个文件。
    • System.out.println("Decrypting Done"); - 如果它抛出异常则不会。
    • 为什么还有这么小的缓冲区? 24字节有什么原因吗?
    • 嗯,是的,你是对的,它不是抛出异常,而是它只是它的一种基本类型。你可以很容易地编辑它你想要我怎么想。不,没有任何特别的理由使用小缓冲区。我相信使用更大的不会有问题。
    • Whatsapp 更新了他们的加密。现在是文件名是“msgstore.db.crypt5”而不是“msgstore.db.crypt”。有什么新的解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多