Guest User

Java unzip decrypt

a guest
May 9th, 2010
896
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import java.io.IOException;
  2. import java.io.InputStream;
  3.  
  4. public class ZipDecryptInputStream extends InputStream {
  5.     private static final int[] CRC_TABLE = new int[256];
  6.     // compute the table
  7.     // (could also have it pre-computed - see http://snippets.dzone.com/tag/crc32)
  8.     static {
  9.         for (int i = 0; i < 256; i++) {
  10.             int r = i;
  11.             for (int j = 0; j < 8; j++) {
  12.                 if ((r & 1) == 1) {
  13.                     r = (r >>> 1) ^ 0xedb88320;
  14.                 } else {
  15.                     r >>>= 1;
  16.                 }
  17.             }
  18.             CRC_TABLE[i] = r;
  19.         }
  20.     }
  21.  
  22.     private static final int DECRYPT_HEADER_SIZE = 12;
  23.     private static final int[] LFH_SIGNATURE = {0x50, 0x4b, 0x03, 0x04};
  24.  
  25.     private final InputStream delegate;
  26.     private final String password;
  27.     private final int keys[] = new int[3];
  28.  
  29.     private State state = State.SIGNATURE;
  30.     private int skipBytes;
  31.     private int compressedSize;
  32.     private int value;
  33.     private int valuePos;
  34.     private int valueInc;
  35.     private byte[] crc = new byte[4];
  36.  
  37.     public ZipDecryptInputStream(InputStream stream, String password) {
  38.         this.delegate = stream;
  39.         this.password = password;
  40.     }
  41.  
  42.     @Override
  43.     public int read() throws IOException {
  44.         int result = delegate.read();
  45.         if (skipBytes == 0) {
  46.             switch (state) {
  47.                 case SIGNATURE:
  48.                     if (result != LFH_SIGNATURE[valuePos]) {
  49.                         state = State.TAIL;
  50.                     } else {
  51.                         valuePos++;
  52.                         if (valuePos >= LFH_SIGNATURE.length) {
  53.                             skipBytes = 2;
  54.                             state = State.FLAGS;
  55.                         }
  56.                     }
  57.                     break;
  58.                 case FLAGS:
  59.                     if ((result & 1) == 0) {
  60.                         throw new IllegalStateException("ZIP not password protected.");
  61.                     }
  62.                     if ((result & 64) == 64) {
  63.                         throw new IllegalStateException("Strong encryption used.");
  64.                     }
  65.                     if ((result & 8) == 8) {
  66.                         throw new IllegalStateException("Unsupported ZIP format.");
  67.                     }
  68.                     result -= 1;
  69.                     compressedSize = 0;
  70.                     valuePos = 0;
  71.                     valueInc = DECRYPT_HEADER_SIZE;
  72.                     state = State.CRC;
  73.                     skipBytes = 10;
  74.                     break;
  75.                 case CRC:
  76.                     crc[3] = (byte) (result & 0xFF);  
  77.                     crc[2] = (byte) ((result >> 8) & 0xFF);  
  78.                     crc[1] = (byte) ((result >> 16) & 0xFF);  
  79.                     crc[0] = (byte) ((result >> 24) & 0xFF);
  80.                     if(crc[2] > 0 || crc[1] > 0 || crc[2] > 0)
  81.                         throw new IllegalStateException("CRC with more than 1 byte, WTF!");
  82.                    
  83.                     state = State.COMPRESSED_SIZE;
  84.                     break;
  85.                 case COMPRESSED_SIZE:
  86.                     compressedSize += result << (8 * valuePos);
  87.                     result -= valueInc;
  88.                     if (result < 0) {
  89.                         valueInc = 1;
  90.                         result += 256;
  91.                     } else {
  92.                         valueInc = 0;
  93.                     }
  94.                     valuePos++;
  95.                     if (valuePos > 3) {
  96.                         valuePos = 0;
  97.                         value = 0;
  98.                         state = State.FN_LENGTH;
  99.                         skipBytes = 4;
  100.                     }
  101.                     break;
  102.                 case FN_LENGTH:
  103.                 case EF_LENGTH:
  104.                     value += result << 8 * valuePos;
  105.                     if (valuePos == 1) {
  106.                         valuePos = 0;
  107.                         if (state == State.FN_LENGTH) {
  108.                             state = State.EF_LENGTH;
  109.                         } else {
  110.                             state = State.HEADER;
  111.                             skipBytes = value;
  112.                         }
  113.                     } else {
  114.                         valuePos = 1;
  115.                     }
  116.                     break;
  117.                 case HEADER:
  118.                     initKeys(password);
  119.                     for (int i = 0; i < DECRYPT_HEADER_SIZE; i++) {
  120.                         if(i+1 == DECRYPT_HEADER_SIZE && ((byte)(result ^ decryptByte()) != crc[3]))
  121.                             throw new IllegalStateException("Wrong password!");
  122.                        
  123.                         updateKeys((byte) (result ^ decryptByte()));
  124.                         result = delegate.read();
  125.                     }
  126.                     compressedSize -= DECRYPT_HEADER_SIZE;
  127.                     state = State.DATA;
  128.                     // intentionally no break
  129.                 case DATA:
  130.                     result = (result ^ decryptByte()) & 0xff;
  131.                     updateKeys((byte) result);
  132.                     compressedSize--;
  133.                     if (compressedSize == 0) {
  134.                         valuePos = 0;
  135.                         state = State.SIGNATURE;
  136.                     }
  137.                     break;
  138.                 case TAIL:
  139.                     // do nothing
  140.             }
  141.         } else {
  142.             skipBytes--;
  143.         }
  144.         return result;
  145.     }
  146.  
  147.     @Override
  148.     public void close() throws IOException {
  149.         delegate.close();
  150.         super.close();
  151.     }
  152.  
  153.     private void initKeys(String password) {
  154.         keys[0] = 305419896;
  155.         keys[1] = 591751049;
  156.         keys[2] = 878082192;
  157.         for (int i = 0; i < password.length(); i++) {
  158.             updateKeys((byte) (password.charAt(i) & 0xff));
  159.         }
  160.     }
  161.  
  162.     private void updateKeys(byte charAt) {
  163.         keys[0] = crc32(keys[0], charAt);
  164.         keys[1] += keys[0] & 0xff;
  165.         keys[1] = keys[1] * 134775813 + 1;
  166.         keys[2] = crc32(keys[2], (byte) (keys[1] >> 24));
  167.     }
  168.  
  169.     private byte decryptByte() {
  170.         int temp = keys[2] | 2;
  171.         return (byte) ((temp * (temp ^ 1)) >>> 8);
  172.     }
  173.  
  174.     private int crc32(int oldCrc, byte charAt) {
  175.         return ((oldCrc >>> 8) ^ CRC_TABLE[(oldCrc ^ charAt) & 0xff]);
  176.     }
  177.  
  178.     private static enum State {
  179.         SIGNATURE, FLAGS, COMPRESSED_SIZE, FN_LENGTH, EF_LENGTH, HEADER, DATA, TAIL, CRC
  180.     }
  181. }
RAW Paste Data

Adblocker detected! Please consider disabling it...

We've detected AdBlock Plus or some other adblocking software preventing Pastebin.com from fully loading.

We don't have any obnoxious sound, or popup ads, we actively block these annoying types of ads!

Please add Pastebin.com to your ad blocker whitelist or disable your adblocking software.

×