Simple zip compressor to instead WinRAR.

I am gonna write blogs via English as current as I do. The first article is regarding to pack and encrypt files to instead WinRAR as a simple solution. 

The principle is just utilizing AES algorithm to pack designated folder into one file, or release the designated file to folder. Here is the code without notes, later I will add up them If possible. Hope you can understand.

Note: file name maybe too short to safe, because lesser content will cause higher chance to be deciphered.

 

package com.encrypt;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.MessageDigest;
import java.security.SecureRandom;
import java.security.Security;
import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.zip.DataFormatException;
import java.util.zip.Deflater;
import java.util.zip.Inflater;

import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.DESedeKeySpec;
import javax.crypto.spec.GCMParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

public class EasyZipper {

    public static void main(String[] args) {
//        args = new String[]{"true", "hh", "ffedddddddddddddddddddddddddddddsssssssssssswf", "dwefewfewfewfewfwefwef"};
        boolean compress = Boolean.parseBoolean(args[0]);
        String fileName = args[1];
        byte[] key = args[2].getBytes();
        byte[] initialVector = null;

        try {
                if (args.length<4||args[3]==null){
                initialVector = MessageDigest.getInstance("MD5").digest(PRE_TEXT.getBytes());
            }else{
                initialVector = args[3].getBytes();
            }
            
            System.out.println(compress?"EnCRYPT":"DeCRYPT");
            System.out.println("DIR:"+fileName);
            System.out.println("PW:"+args[2]);
            System.out.println("Vector:"+(args.length<4||args[3]==null?"":args[3]));

            if (compress) {
                new EasyZipper().ziper(new File(fileName), key, initialVector);
                System.out.println("End:"+fileName+".zip");
            }else {
                new EasyZipper().unZiper(new File(fileName+".zip"), key, initialVector);
                System.out.println("End:"+fileName);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    public static int getInt(byte b) {
        int num = (int) b;
        if (num < 0) {
            num = num + 256;
        }
        return num;
    }
    public static String getHexString(byte b) {
        int tmpnum = getInt(b);
        String sTemp = Integer.toHexString(tmpnum).toUpperCase();
        if (sTemp.length() == 1) {
            sTemp = "0" + sTemp;
        }
        return sTemp;
    }
    public static String getHexString(byte[] bytes) {
        StringBuilder buffer = new StringBuilder();
        for (int i = 0; i < bytes.length; i++) {
            buffer.append(getHexString(bytes[i]));
        }
        return buffer.toString();
    }

    private static int[] preHexadecimal = new int[] {
            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
            0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,
            -1,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,-1,-1,-1,
            -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
            -1,10,11,12,13,14,15
    };
    
    public static byte[] hex2Bytes(String s) throws IOException {
        if (s.length() % 2 != 0) { throw new IOException("hexadecimal string with odd number of characters"); }
        byte[] abyte0 = new byte[s.length() / 2];
        char[] sChars = s.toCharArray();
        for (int k=0,j=0; k<abyte0.length; k++) {
            int l = preHexadecimal[(int)sChars[j++]];
            if (l == -1) {throw new IOException("hexadecimal string contains non hex character");}
            abyte0[k] = (byte) (((l & 0xf) << 4) + (preHexadecimal[(int)sChars[j++]] & 0xf));
        }
        return abyte0;
    }
private static final String PRE_TEXT = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"; private static final int JUMP=17; public void unZiper(File file, byte[] rowKey, byte[] initialVector) throws Exception { byte[] key384 = halfXOR(MessageDigest.getInstance("SHA-384").digest(rowKey)); byte[] desKey = halfXOR(MessageDigest.getInstance("SHA-384").digest(doDESEncrypt(256, key384, initialVector, rowKey))); byte[] aesKey = halfXOR(MessageDigest.getInstance("SHA-384").digest(doAESEncrypt(256, desKey, initialVector, rowKey))); InputStream fis = new BufferedInputStream(new FileInputStream(file)); byte[] reading=new byte[1024],bytes; String fileDescription = null; int len=0,length=0,tmp=0; while(true){ try { if (len==reading.length) { reading=Arrays.copyOf(reading, reading.length*2); } if (len/JUMP==(len+8)/JUMP) { tmp = fis.read(reading, len, 8); }else { length = ((len+8)/JUMP*JUMP)-len; tmp = fis.read(reading, len, length); if(tmp>0) { fis.skip(1); tmp = fis.read(reading, len+length, 8-length); } } bytes = Arrays.copyOf(reading, len+=8); bytes = doAESDecrypt(256, aesKey, initialVector, bytes); bytes = doDESDecrypt(256, desKey, initialVector, bytes); bytes = decompress(bytes); fileDescription = new String(bytes, "UTF-8").trim(); tmp=-1; }catch(Exception e) { // e.printStackTrace(); }finally { if (tmp<0){ break; } } } String[] array = fileDescription.split(","); for(int k=0; k<array.length; k++) { if (PRE_TEXT.endsWith(array[k])) {break;} File tmpfile = new File(new File("").getAbsoluteFile()+File.separator+array[k]); if (Integer.parseInt(array[k+=1])==-1) {k+=1;tmpfile.mkdirs();continue;} tmpfile.getParentFile().mkdirs(); tmpfile.createNewFile(); OutputStream fos = new BufferedOutputStream(new FileOutputStream(tmpfile)); bytes = new byte[Integer.parseInt(array[k+=1])]; if (bytes.length==0) {continue;} len=0; int jumpNext=JUMP,jump=0; while(true){ if (jump+8<jumpNext) { tmp = fis.read(bytes, len, 8); }else { tmp = fis.read(bytes, len, jumpNext-jump); if(tmp>-1&&tmp<8) { fis.skip(1); tmp = fis.read(bytes, len+tmp, 8-tmp); } } jump+=8;len+=8; if (tmp<0||len==bytes.length){ break; } if (jump==jumpNext) { jump+=1; jumpNext+=1+JUMP; fis.skip(1); }else if (jump>jumpNext) { jumpNext+=JUMP; } } System.out.println(tmpfile.getPath()+","+array[k-1]+","+len+","); // bytes = decompress(bytes);  bytes = doAESDecrypt(256, aesKey, initialVector, bytes); bytes = doDESDecrypt(256, desKey, initialVector, bytes); fos.write(decompress(bytes)); fos.flush(); fos.close(); } fis.close(); } public void ziper(File root, byte[] rowKey, byte[] initialVector) throws Exception { byte[] key384 = halfXOR(MessageDigest.getInstance("SHA-384").digest(rowKey)); byte[] desKey = halfXOR(MessageDigest.getInstance("SHA-384").digest(doDESEncrypt(256, key384, initialVector, rowKey))); byte[] aesKey = halfXOR(MessageDigest.getInstance("SHA-384").digest(doAESEncrypt(256, desKey, initialVector, rowKey))); File zipData = new File(root.getName()+".zipa"); OutputStream dataFos = new BufferedOutputStream(new FileOutputStream(zipData)); byte[] buffer = new byte[1024000]; String fileDescription = ""; List<File> fileList = new ArrayList<File>(); fileList.addAll(Arrays.asList(root.listFiles())); for (int i=0; i<fileList.size(); i++) { if (fileList.get(i).isDirectory()) { fileList.addAll(Arrays.asList(fileList.get(i).listFiles())); } } for (File subFile : fileList) { if (subFile.isDirectory()) { fileDescription+=subFile.getPath()+",-1,-1,"; continue; } if (subFile.length()==0) { fileDescription+=subFile.getPath()+",0,0,"; continue; } InputStream fis = new BufferedInputStream(new FileInputStream(subFile)); ByteArrayOutputStream bos = new ByteArrayOutputStream(); int len=0; while ((len = fis.read(buffer)) != -1) { bos.write(buffer, 0, len); } fis.close(); byte[] bytes = bos.toByteArray(); bos.close(); bytes = compress(bytes); bytes = doDESEncrypt(256, desKey, initialVector, bytes); bytes = doAESEncrypt(256, aesKey, initialVector, bytes); len = bytes.length; // bytes=compress(bytes); ByteArrayOutputStream bbos = new ByteArrayOutputStream(); for(int i=0; i<bytes.length; i+=JUMP) { if (i+JUMP>=bytes.length) { bbos.write(bytes, i, bytes.length-i); }else { bbos.write(bytes, i, JUMP); bbos.write((byte) (Math.random()*256)); } } bytes = bbos.toByteArray(); bbos.close(); dataFos.write(bytes); dataFos.flush(); fileDescription+=subFile.getPath()+","+subFile.length()+","+len+","; System.out.println(subFile.getPath()+","+subFile.length()+","+len+","); } dataFos.close(); OutputStream fos = new BufferedOutputStream(new FileOutputStream(root.getName()+".zip")); byte[] bytes = (fileDescription+PRE_TEXT).getBytes("UTF-8"); bytes = compress(bytes); bytes = doDESEncrypt(256, desKey, initialVector, bytes); bytes = doAESEncrypt(256, aesKey, initialVector, bytes); ByteArrayOutputStream bbos = new ByteArrayOutputStream(); for(int i=0; i<bytes.length; i+=JUMP) { if (i+JUMP>=bytes.length) { bbos.write(bytes, i, bytes.length-i); }else { bbos.write(bytes, i, JUMP); bbos.write((byte) (Math.random()*256)); } } bytes = bbos.toByteArray(); bbos.close(); //bytes=compress(bytes);  fos.write(bytes); fos.flush(); InputStream fis = new BufferedInputStream(new FileInputStream(zipData)); bytes = new byte[10240000]; while(true){ int length = fis.read(bytes); if (length<1){ break; } fos.write(bytes, 0, length); fos.flush(); } fis.close(); fos.close(); zipData.delete(); } private static final byte[] halfXOR(byte[] original) { byte[] newArray = Arrays.copyOf(original, original.length/2); for(int i=0; i<newArray.length;i++) { newArray[i] ^= original[newArray.length+i]; } return newArray; } public static final byte[] doAESDecrypt(int length, byte[] key, byte[] initialVector, byte[] text) throws Exception { return doAESEncrypt(false,length,key,initialVector,text); } public static final byte[] doAESEncrypt(int length, byte[] key, byte[] initialVector, byte[] text) throws Exception { return doAESEncrypt(true,length,key,initialVector,text); } private static final byte[] doAESEncrypt(boolean encrypt, int length, byte[] key, byte[] initialVector, byte[] text) throws Exception { KeyGenerator kgen = KeyGenerator.getInstance("AES"); SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG"); secureRandom.setSeed(Arrays.copyOf(key, key.length)); kgen.init(length, secureRandom); SecretKey secretKey = kgen.generateKey(); SecretKeySpec secretKeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); if (initialVector==null||initialVector.length==0){ initialVector = new byte[16]; }else { initialVector = Arrays.copyOf(initialVector, 16); } IvParameterSpec iv = new IvParameterSpec(initialVector); cipher.init(encrypt?Cipher.ENCRYPT_MODE:Cipher.DECRYPT_MODE, secretKeySpec, iv); return cipher.doFinal(text); } public static final byte[] doDESDecrypt(int length, byte[] key, byte[] initialVector, byte[] text) throws Exception { return doDESEncrypt(false,length,key,initialVector,text); } public static final byte[] doDESEncrypt(int length, byte[] key, byte[] initialVector, byte[] text) throws Exception { return doDESEncrypt(true,length,key,initialVector,text); } private static final byte[] doDESEncrypt(boolean encrypt, int length, byte[] key, byte[] initialVector, byte[] encryptText) throws Exception { int len = encryptText.length; if (encryptText.length % 8 != 0) { len = encryptText.length - encryptText.length % 8 + 8; } byte[] needData = null; if (len != 0) needData = new byte[len]; for (int i = 0; i < len; i++) { needData[i] = 0x00; } System.arraycopy(encryptText, 0, needData, 0, encryptText.length); byte[] k = Arrays.copyOf(key, 24); if (key.length<k.length) { System.arraycopy(key, 0, k, key.length, k.length-key.length); } KeySpec ks = new DESedeKeySpec(k); SecretKeyFactory kf = SecretKeyFactory.getInstance("DESede"); SecretKey ky = kf.generateSecret(ks); Cipher cipher = Cipher.getInstance("DESede/CBC/PKCS5Padding"); if (initialVector==null||initialVector.length==0){ initialVector = new byte[8]; }else { initialVector = Arrays.copyOf(initialVector, 8); } IvParameterSpec iv = new IvParameterSpec(initialVector); cipher.init(encrypt?Cipher.ENCRYPT_MODE:Cipher.DECRYPT_MODE, ky, iv); byte[] returned = cipher.doFinal(needData); int last0 = returned.length; for(;last0>-1&&returned[last0-1]==0;last0-=1) {} if (last0!=returned.length) {returned = Arrays.copyOf(returned, last0);} return returned; } public static byte[] compress(byte[] data) { return compress(data, 0, data.length); } public static byte[] decompress(byte[] data) throws DataFormatException { return decompress(data, 0, data.length); } public static byte[] compress(byte[] data, int offset, int len) { byte[] output = new byte[0]; Deflater compresser = new Deflater(Deflater.BEST_COMPRESSION); compresser.setInput(data, offset, len); compresser.finish(); ByteArrayOutputStream bos = new ByteArrayOutputStream(len); byte[] buf = new byte[1024]; while (!compresser.finished()) { int count = compresser.deflate(buf); if (count<1) {break;} bos.write(buf, 0, count); } output = bos.toByteArray(); try { bos.close(); } catch (IOException e) { // e.printStackTrace();  } compresser.end(); return output; } public static byte[] decompress(byte[] data, int offset, int len) throws DataFormatException { byte[] output = new byte[0]; Inflater decompresser = new Inflater(); decompresser.setInput(data, offset, len); ByteArrayOutputStream baos = new ByteArrayOutputStream(len); byte[] buff = new byte[1024]; while (!decompresser.finished()) { int count = decompresser.inflate(buff); if (count<1) {break;} baos.write(buff, 0, count); } output = baos.toByteArray(); try { baos.close(); } catch (IOException e) { // e.printStackTrace();  } decompresser.end(); return output; } }

 

Lesser chinese content were not allowed to be set into Java category, so I added trash charactors here:

中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。中文少的内容不允许投稿到java分类啊,只能随便写点内容了。


    public static int getInt(byte b) {        int num = (int) b;        if (num < 0) {            num = num + 256;        }        return num;    }    public static String getHexString(byte b) {        int tmpnum = getInt(b);        String sTemp = Integer.toHexString(tmpnum).toUpperCase();        if (sTemp.length() == 1) {            sTemp = "0" + sTemp;        }        return sTemp;    }    public static String getHexString(byte[] bytes) {        StringBuilder buffer = new StringBuilder();        for (int i = 0; i < bytes.length; i++) {        buffer.append(getHexString(bytes[i]));        }        return buffer.toString();    }
    private static int[] preHexadecimal = new int[] {    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    0,1,2,3,4,5,6,7,8,9,-1,-1,-1,-1,-1,-1,    -1,26,27,28,29,30,31,32,-1,-1,-1,-1,-1,-1,-1,-1,    -1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,    -1,10,11,12,13,14,15    };        public static byte[] hex2Bytes(String s) throws IOException {        if (s.length() % 2 != 0) { throw new IOException("hexadecimal string with odd number of characters"); }        byte[] abyte0 = new byte[s.length() / 2];        char[] sChars = s.toCharArray();        for (int k=0,j=0; k<abyte0.length; k++) {        int l = preHexadecimal[(int)sChars[j++]];            if (l == -1) {throw new IOException("hexadecimal string contains non hex character");}            abyte0[k] = (byte) (((l & 0xf) << 4) + (preHexadecimal[(int)sChars[j++]] & 0xf));        }        return abyte0;    }

posted on 2020-08-10 00:59  過眼云煙  阅读(221)  评论(0)    收藏  举报

导航