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; }
浙公网安备 33010602011771号