package com.zbwt.archives.util.encrypteDecryption;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Arrays;import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class AESTwo {
private static KeyGenerator kgen;
private static SecureRandom secureRandom;
private static SecretKeySpec key;
private static Cipher cipher;
/**
 * AES加密算法
 */
public AESTwo() {
}
private static void init(String keyWord){
try {
kgen = KeyGenerator.getInstance("AES");
secureRandom = SecureRandom.getInstance("SHA1PRNG" );  
secureRandom.setSeed(keyWord.getBytes());  
kgen.init(128,secureRandom);  
SecretKey secretKey = kgen.generateKey();  
byte[] enCodeFormat = secretKey.getEncoded();  
key = new SecretKeySpec(enCodeFormat, "AES");  
cipher = Cipher.getInstance("AES");// 创建密码器  
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/********************************对文件进行加密解密*********************************************************/
/**
 * @param fileName  加密的文件路径
 * @param fileNameEncrypt 加密后的文件路径 当fileNameEncrypt为null时加密文件代替原文件
 * @param keyWord 加密密钥
 *  
 */
public static void encryptFile(String fileName,String fileNameEncrypt, String keyWord){  
try {
boolean replace = false;
if(fileNameEncrypt==null || fileNameEncrypt.equals("")){
fileNameEncrypt = fileName+".tem";
replace = true;
}
init(keyWord);
cipher.init(Cipher.ENCRYPT_MODE, key);// 初始化  
  File file = new File(fileNameEncrypt);
if (!file.exists())
file.createNewFile();
FileInputStream fileinputstream=new FileInputStream(fileName);
FileOutputStream out = new FileOutputStream(file);
byte bytes[] = new byte[131072]; //因在断点下载时用到,不能修改 除非 断点下载处修改
byte enbytes[] = null;
int line = 0;
while ((line = fileinputstream.read(bytes)) != -1) {
enbytes = cipher.doFinal(Arrays.copyOfRange(bytes, 0, line));
    out.write(enbytes, 0, enbytes.length);
}
out.close();
fileinputstream.close();

if(replace){
File oldFile  = new File(fileName);
oldFile.delete();
File newFile = new File(fileNameEncrypt);
newFile.renameTo(oldFile);
}

        } catch (InvalidKeyException e) {  
            e.printStackTrace();  
        } catch (UnsupportedEncodingException e) {  
            e.printStackTrace();  
        } catch (IllegalBlockSizeException e) {  
            e.printStackTrace();  
        } catch (BadPaddingException e) {  
            e.printStackTrace();  
        } catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

  /**解密 
   * @param content  待解密内容 
   * @param keyWord 解密密钥 
   * @return  byte[]
   */  
public static void decryptFile(String encryptFileName,String decryptFileName, String keyWord) {
try {  
boolean replace = false;
if(decryptFileName==null || decryptFileName.equals("")){
decryptFileName = encryptFileName+".tem";
replace = true;
}
init(keyWord);
cipher.init(Cipher.DECRYPT_MODE, key);// 初始化  
File file = new File(decryptFileName); //解密后的文件
if (!file.exists())
file.createNewFile();
FileInputStream fileinputstream=new FileInputStream(encryptFileName); //要解密的文件
FileOutputStream out = new FileOutputStream(file);
byte bytes[] = new byte[131080]; //因在断点下载时用到,不能修改 除非 断点下载处修改
byte enbytes[] = null;
int line = 0;
while ((line = fileinputstream.read(bytes)) != -1) {
enbytes = cipher.doFinal(Arrays.copyOfRange(bytes, 0, line));
    out.write(enbytes, 0, enbytes.length);
}
out.close();
fileinputstream.close();

if(replace){
File oldFile  = new File(encryptFileName);
oldFile.delete();
File newFile = new File(decryptFileName);
newFile.renameTo(oldFile);
}
} catch (InvalidKeyException e) {  
            e.printStackTrace();  
        } catch (IllegalBlockSizeException e) {  
                 e.printStackTrace();  
} catch (BadPaddingException e) {  
                 e.printStackTrace();  
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

/********************************对文件进行加密解密结束*****************************************************/

/**将二进制转换成16进制 
 * @param buf 
 * @return  String
  */  
public static String parseByte2HexStr(byte buf[]) {  
StringBuffer sb = new StringBuffer();  
        for (int i = 0; i < buf.length; i++) {  
         String hex = Integer.toHexString(buf[i] & 0xFF);  
         if (hex.length() == 1) {  
         hex = '0' + hex;  
         }  
         sb.append(hex.toUpperCase());  
        }  
        return sb.toString();  
}
/**将16进制转换为二进制 
 * @param hexStr 
 * @return  byte[]
 */  
public static byte[] parseHexStr2Byte(String hexStr) {  
if (hexStr.length() < 1)  
return null;  
byte[] result = new byte[hexStr.length()/2];  
for (int i = 0;i< hexStr.length()/2; i++) {  
int high = Integer.parseInt(hexStr.substring(i*2, i*2+1), 16);  
          int low = Integer.parseInt(hexStr.substring(i*2+1, i*2+2), 16);  
            result[i] = (byte) (high * 16 + low);  
}  
return result;  
}  

public static void main(String[] args) {
AESTwo.encryptFile("D:\\tcas4home\\certificateKey\\jingoal.rar", "D:\\tcas4home\\certificateKey\\复件 (2) jingoal.rar", "ABCDEFGHABCDEFGH");
AESTwo.decryptFile("D:\\tcas4home\\certificateKey\\复件 (2) jingoal.rar", "D:\\tcas4home\\certificateKey\\复件 jingoal.rar", "ABCDEFGHABCDEFGH");
}
}报异常:
javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.SunJCE_f.b(DashoA13*..)
at com.sun.crypto.provider.AESCipher.engineDoFinal(DashoA13*..)
at javax.crypto.Cipher.doFinal(DashoA13*..)
在网上搜的错误原因说是
这主要是因为加密后的byte数组是不能强制转换成字符串的,换言之:字符串和byte数组在这种情况下不是互逆的;可是没看出上述程序有什么逆转啊 还有我现在解密时读的字节流是 byte bytes[] = new byte[131080];  如果把 131080改成 131088就不报错了  可是因为项目中这个 131080因为在文件下载时需要支持断点下载 所以给写死了 无法修改。纠结啊。。
还有一种情况不报错,就是 在上述程序中 文件小于 128kb时加解密都没问题高分求牛人 解决。。