Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main;
- import java.io.BufferedInputStream;
- import java.io.ByteArrayInputStream;
- import java.io.ByteArrayOutputStream;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.security.Security;
- import java.util.Arrays;
- import java.util.zip.DeflaterInputStream;
- import java.util.zip.Inflater;
- import java.util.zip.InflaterInputStream;
- import javax.crypto.Cipher;
- import javax.crypto.CipherInputStream;
- import javax.crypto.spec.IvParameterSpec;
- import javax.crypto.spec.SecretKeySpec;
- import org.bouncycastle.jce.provider.BouncyCastleProvider;
- import com.google.common.io.ByteStreams;
- import com.google.common.io.Files;
- public class WhatsappCrypto {
- private byte[] c12Data;
- private byte[] header;
- private byte[] footer;
- private byte[] keyData;
- private byte[] t1;
- private byte[] t2;
- private byte[] key;
- private byte[] iv;
- /**
- * Constructor
- */
- public WhatsappCrypto() {
- super();
- }
- /**
- * Encrypt
- *
- * @param sqliteFile
- * @param c12File
- * @param keyFile
- * @return
- */
- public boolean encrypt(String sqliteFile, String c12File, String keyFile) {
- try {
- File sqlite = new File(sqliteFile);
- // Compress
- DeflaterInputStream dis = this.compress(new FileInputStream(sqlite));
- // Encrypt
- CipherInputStream cipherStream = this.crypto(Cipher.ENCRYPT_MODE, dis, this.key, this.iv);
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- bos.write(this.header);
- bos.write(ByteStreams.toByteArray(cipherStream));
- bos.write(this.footer);
- cipherStream.close();
- dis.close();
- // Write to file
- FileOutputStream fos = new FileOutputStream(new File(c12File));
- bos.writeTo(fos);
- bos.close();
- return true;
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- return false;
- }
- /**
- * Decrypt
- *
- * @param keyFile
- * @param c12File
- * @param sqliteFile
- * @return
- */
- public boolean decrypt(String keyFile, String c12File, String sqliteFile) {
- if (this.readKeyData(keyFile) && this.readC12Data(c12File)) {
- try {
- byte[] tempBuffer = Arrays.copyOfRange(this.c12Data, 67, this.c12Data.length - 20);
- InputStream is = new ByteArrayInputStream(tempBuffer);
- // Decrypt
- CipherInputStream cipherStream = this.crypto(Cipher.DECRYPT_MODE, is, this.key, this.iv);
- // Decompress
- InflaterInputStream iis = this.decompress(cipherStream);
- // Write to file
- Files.write(ByteStreams.toByteArray(iis), new File(sqliteFile));
- cipherStream.close();
- is.close();
- return this.isValidSqlite(sqliteFile);
- } catch (Exception ex) {
- ex.printStackTrace();
- }
- return false;
- }
- return false;
- }
- /**
- * Read key data
- *
- * @param keyFile
- * @return
- */
- private boolean readKeyData(String keyFile) {
- try {
- InputStream is = new FileInputStream(keyFile);
- this.keyData = new byte[158];
- is.read(this.keyData);
- this.t1 = new byte[32];
- System.arraycopy(this.keyData, 30, this.t1, 0, 32);
- this.key = new byte[32];
- System.arraycopy(this.keyData, 126, this.key, 0, 32);
- is.close();
- return true;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return false;
- }
- /**
- * Read c12 data
- *
- * @param c12File
- * @return
- */
- private boolean readC12Data(String c12File) {
- try {
- InputStream c12InStream = new BufferedInputStream(new FileInputStream(c12File));
- this.c12Data = ByteStreams.toByteArray(c12InStream);
- this.header = Arrays.copyOfRange(this.c12Data, 0, 67);
- this.footer = Arrays.copyOfRange(this.c12Data, this.c12Data.length - 20, this.c12Data.length);
- this.t2 = new byte[32];
- System.arraycopy(this.header, 3, this.t2, 0, 32);
- this.iv = new byte[16];
- System.arraycopy(this.header, 51, this.iv, 0, 16);
- if (!new String(this.t1, 0, this.t1.length, "ASCII").equals(new String(this.t2, 0, this.t2.length, "ASCII")))
- return false;
- return true;
- } catch (IOException e) {
- e.printStackTrace();
- }
- return false;
- }
- /**
- * Crypto
- *
- * @param type
- * @param is
- * @param key
- * @param iv
- * @return
- * @throws Exception
- */
- private CipherInputStream crypto(int type, InputStream is, byte[] key, byte[] iv) throws Exception {
- Security.addProvider(new BouncyCastleProvider());
- Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
- cipher.init(type, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
- return new CipherInputStream(is, cipher);
- }
- /**
- * Decompress
- *
- * @param inStream
- * @return
- */
- private InflaterInputStream decompress(InputStream inStream) {
- try {
- return new InflaterInputStream(inStream, new Inflater(false));
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * Compress
- *
- * @param inStream
- * @return
- */
- private DeflaterInputStream compress(InputStream inStream) {
- try {
- return new DeflaterInputStream(inStream);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
- /**
- * Check if valid sqlite
- *
- * @param sqliteFile
- * @return
- */
- private boolean isValidSqlite(String sqliteFile) {
- try {
- InputStream inStream = new FileInputStream(sqliteFile);
- byte[] sqlData = new byte[6];
- inStream.read(sqlData);
- byte[] ms = new byte[6];
- System.arraycopy(sqlData, 0, ms, 0, 6);
- inStream.close();
- if (!new String(ms, 0, ms.length, "ASCII").toLowerCase().equals("sqlite")) {
- new File(sqliteFile).delete();
- return false;
- } else {
- return true;
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- return false;
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment