Fakedo0r

Whatsapp Crypt12

Jul 13th, 2018
99
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.84 KB | None | 0 0
  1. package main;
  2.  
  3. import java.io.BufferedInputStream;
  4. import java.io.ByteArrayInputStream;
  5. import java.io.ByteArrayOutputStream;
  6. import java.io.File;
  7. import java.io.FileInputStream;
  8. import java.io.FileOutputStream;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.security.Security;
  12. import java.util.Arrays;
  13. import java.util.zip.DeflaterInputStream;
  14. import java.util.zip.Inflater;
  15. import java.util.zip.InflaterInputStream;
  16.  
  17. import javax.crypto.Cipher;
  18. import javax.crypto.CipherInputStream;
  19. import javax.crypto.spec.IvParameterSpec;
  20. import javax.crypto.spec.SecretKeySpec;
  21.  
  22. import org.bouncycastle.jce.provider.BouncyCastleProvider;
  23.  
  24. import com.google.common.io.ByteStreams;
  25. import com.google.common.io.Files;
  26.  
  27. public class WhatsappCrypto {
  28.    
  29.     private byte[] c12Data;
  30.    
  31.     private byte[] header;
  32.     private byte[] footer;
  33.    
  34.     private byte[] keyData;
  35.     private byte[] t1;
  36.     private byte[] t2;
  37.     private byte[] key;
  38.     private byte[] iv;
  39.    
  40.     /**
  41.      * Constructor
  42.      */
  43.     public WhatsappCrypto() {
  44.         super();
  45.     }
  46.  
  47.     /**
  48.      * Encrypt
  49.      *
  50.      * @param sqliteFile
  51.      * @param c12File
  52.      * @param keyFile
  53.      * @return
  54.      */
  55.     public boolean encrypt(String sqliteFile, String c12File, String keyFile) {
  56.         try {
  57.             File sqlite = new File(sqliteFile);
  58.            
  59.             // Compress
  60.             DeflaterInputStream dis = this.compress(new FileInputStream(sqlite));
  61.  
  62.             // Encrypt
  63.             CipherInputStream cipherStream = this.crypto(Cipher.ENCRYPT_MODE, dis, this.key, this.iv);
  64.            
  65.             ByteArrayOutputStream bos = new ByteArrayOutputStream();
  66.            
  67.             bos.write(this.header);
  68.             bos.write(ByteStreams.toByteArray(cipherStream));
  69.             bos.write(this.footer);
  70.            
  71.             cipherStream.close();
  72.             dis.close();
  73.            
  74.             // Write to file
  75.             FileOutputStream fos = new FileOutputStream(new File(c12File));
  76.             bos.writeTo(fos);
  77.             bos.close();
  78.            
  79.             return true;
  80.         } catch (Exception ex) {
  81.             ex.printStackTrace();
  82.         }
  83.        
  84.         return false;
  85.     }
  86.    
  87.     /**
  88.      * Decrypt
  89.      *
  90.      * @param keyFile
  91.      * @param c12File
  92.      * @param sqliteFile
  93.      * @return
  94.      */
  95.     public boolean decrypt(String keyFile, String c12File, String sqliteFile) {
  96.         if (this.readKeyData(keyFile) && this.readC12Data(c12File)) {
  97.             try {
  98.                 byte[] tempBuffer = Arrays.copyOfRange(this.c12Data, 67, this.c12Data.length - 20);
  99.                 InputStream is = new ByteArrayInputStream(tempBuffer);
  100.                
  101.                 // Decrypt
  102.                 CipherInputStream cipherStream = this.crypto(Cipher.DECRYPT_MODE, is, this.key, this.iv);
  103.  
  104.                 // Decompress
  105.                 InflaterInputStream iis = this.decompress(cipherStream);   
  106.                
  107.                 // Write to file
  108.                 Files.write(ByteStreams.toByteArray(iis), new File(sqliteFile));
  109.                
  110.                 cipherStream.close();
  111.                 is.close();
  112.  
  113.                 return this.isValidSqlite(sqliteFile);
  114.             } catch (Exception ex) {
  115.                 ex.printStackTrace();
  116.             }  
  117.            
  118.             return false;
  119.         }
  120.        
  121.         return false;
  122.     }
  123.        
  124.     /**
  125.      * Read key data
  126.      *
  127.      * @param keyFile
  128.      * @return
  129.      */
  130.     private boolean readKeyData(String keyFile) {      
  131.         try {
  132.             InputStream is = new FileInputStream(keyFile);
  133.            
  134.             this.keyData = new byte[158];
  135.             is.read(this.keyData);
  136.            
  137.             this.t1 = new byte[32];
  138.             System.arraycopy(this.keyData, 30, this.t1, 0, 32);
  139.            
  140.             this.key = new byte[32];
  141.             System.arraycopy(this.keyData, 126, this.key, 0, 32);
  142.            
  143.             is.close();
  144.            
  145.             return true;
  146.         } catch (IOException e) {
  147.             e.printStackTrace();
  148.         }
  149.        
  150.         return false;
  151.     }
  152.        
  153.     /**
  154.      * Read c12 data
  155.      *
  156.      * @param c12File
  157.      * @return
  158.      */
  159.     private boolean readC12Data(String c12File) {
  160.         try {
  161.             InputStream c12InStream = new BufferedInputStream(new FileInputStream(c12File));
  162.            
  163.             this.c12Data = ByteStreams.toByteArray(c12InStream);
  164.            
  165.             this.header = Arrays.copyOfRange(this.c12Data, 0, 67);
  166.             this.footer = Arrays.copyOfRange(this.c12Data, this.c12Data.length - 20, this.c12Data.length);
  167.  
  168.             this.t2 = new byte[32];
  169.             System.arraycopy(this.header, 3, this.t2, 0, 32);
  170.            
  171.             this.iv = new byte[16];
  172.             System.arraycopy(this.header, 51, this.iv, 0, 16);
  173.  
  174.             if (!new String(this.t1, 0, this.t1.length, "ASCII").equals(new String(this.t2, 0, this.t2.length, "ASCII")))
  175.                 return false;
  176.    
  177.             return true;
  178.         } catch (IOException e) {
  179.             e.printStackTrace();
  180.         }
  181.  
  182.         return false;
  183.     }
  184.    
  185.     /**
  186.      * Crypto
  187.      *
  188.      * @param type
  189.      * @param is
  190.      * @param key
  191.      * @param iv
  192.      * @return
  193.      * @throws Exception
  194.      */
  195.     private CipherInputStream crypto(int type, InputStream is, byte[] key, byte[] iv) throws Exception {
  196.         Security.addProvider(new BouncyCastleProvider());
  197.        
  198.         Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "BC");
  199.         cipher.init(type, new SecretKeySpec(key, "AES"), new IvParameterSpec(iv));
  200.         return new CipherInputStream(is, cipher);
  201.     }
  202.    
  203.     /**
  204.      * Decompress
  205.      *
  206.      * @param inStream
  207.      * @return
  208.      */
  209.     private InflaterInputStream decompress(InputStream inStream) {
  210.         try {
  211.             return new InflaterInputStream(inStream, new Inflater(false));
  212.         } catch (Exception e) {
  213.             e.printStackTrace();
  214.         }
  215.        
  216.         return null;
  217.     }
  218.    
  219.     /**
  220.      * Compress
  221.      *
  222.      * @param inStream
  223.      * @return
  224.      */
  225.     private DeflaterInputStream compress(InputStream inStream) {
  226.         try {
  227.             return new DeflaterInputStream(inStream);
  228.         } catch (Exception e) {
  229.             e.printStackTrace();
  230.         }
  231.        
  232.         return null;
  233.     }
  234.    
  235.     /**
  236.      * Check if valid sqlite
  237.      *
  238.      * @param sqliteFile
  239.      * @return
  240.      */
  241.     private boolean isValidSqlite(String sqliteFile) {
  242.         try {
  243.             InputStream inStream = new FileInputStream(sqliteFile);
  244.            
  245.             byte[] sqlData = new byte[6];
  246.             inStream.read(sqlData);
  247.            
  248.             byte[] ms = new byte[6];
  249.             System.arraycopy(sqlData, 0, ms, 0, 6);
  250.            
  251.             inStream.close();
  252.  
  253.             if (!new String(ms, 0, ms.length, "ASCII").toLowerCase().equals("sqlite")) {
  254.                 new File(sqliteFile).delete();
  255.                 return false;
  256.             } else {
  257.                 return true;
  258.             }  
  259.         } catch (Exception e) {
  260.             e.printStackTrace();
  261.         }
  262.  
  263.         return false;
  264.     }
  265. }
Advertisement
Add Comment
Please, Sign In to add comment