Guest User

Java unzip decrypt

a guest
May 9th, 2010
848
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