多平台下AES文件加密的总结,涵盖Windows,Android,Mac,Linux。。
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class AESCrpyt {
private static String TYPE = "AES";
private static int KeySizeAES128 = 16;
private static int BUFFER_SIZE = 8192;
private static Cipher getCipher(int mode,String key) {
//mode =Cipher.DECRYPT_MODE or Cipher.ENCRYPT_MODE
Cipher mCipher;
byte[]keyPtr=new byte[KeySizeAES128];
IvParameterSpecivParam=new IvParameterSpec(keyPtr);
byte[]passPtr=key.getBytes();
try{
mCipher=Cipher.getInstance(TYPE+"/CBC/PKCS5Padding");
for(int i=0;i<KeySizeAES128;i++) {
if(i<passPtr.length) keyPtr[i]=passPtr[i];
else keyPtr[i]=0;
}
SecretKeySpec keySpec=new SecretKeySpec(keyPtr,TYPE);
mCipher.init(mode, keySpec, ivParam);
return mCipher;
}
catch (InvalidKeyException e) {
e.printStackTrace();
}
catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
catch (NoSuchPaddingException e) {
e.printStackTrace();
}
catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
/**
* 解密文件
* @param srcFile
* @param destFile
* @param privateKey
*/
public static void decrypt(String srcFile, String destFile, String privateKey) {
byte[] readBuffer=new byte[BUFFER_SIZE];
Cipher deCipher=getCipher(Cipher.DECRYPT_MODE,privateKey);
if(deCipher==null) return; //init failed.
CipherInputStream fis=null;
BufferedOutputStream fos=null;
int size;
try {
fis = new CipherInputStream(
new BufferedInputStream(
new FileInputStream(srcFile)),deCipher);
fos = new BufferedOutputStream(
new FileOutputStream(mkdirFiles(destFile)));
while((size=fis.read(readBuffer,0,BUFFER_SIZE))>=0) {
fos.write(readBuffer,0,size);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try { fis.close(); } catch(IOException e) {}
}
if (fos != null) {
try { fos.flush(); } catch(IOException e) {}
try { fos.close(); } catch(IOException e) {}
}
}
}
/**
* 加密文件
* @param srcFile
* @param destFile
* @param privateKey
*/
public static void crypt(String srcFile, String destFile, String privateKey) {
byte[] readBuffer=new byte[BUFFER_SIZE];
Cipher enCipher=getCipher(Cipher.ENCRYPT_MODE,privateKey);
if(enCipher==null) return; //init failed.
CipherOutputStream fos=null;
BufferedInputStream fis=null;
int size;
try {
fos = new CipherOutputStream(
new BufferedOutputStream(
new FileOutputStream(destFile)),enCipher);
fis = new BufferedInputStream(
new FileInputStream(mkdirFiles(srcFile)));
while((size=fis.read(readBuffer,0,BUFFER_SIZE))>=0) {
fos.write(readBuffer,0,size);
}
fos.flush();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fis != null) {
try { fis.close(); } catch(IOException e) {}
}
if (fos != null) {
try { fos.flush(); } catch(IOException e) {}
try { fos.close(); } catch(IOException e) {}
}
}
}
private static File mkdirFiles(String filePath) throws IOException {
File file = new File(filePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
file.createNewFile();
return file;
}
public static void main(String[] args) {
AESCrpyt aes = new AESCrpyt();
aes.crypt("/Users/liaomin/Documents/计算机原理.pdf", "/Users/liaomin/Documents/加密_计算机原理.pdf", "111");
aes.decrypt("/Users/liaomin/Documents/加密_计算机原理.pdf", "/Users/liaomin/Documents/解密_计算机原理.pdf", "111");
}
}
测试了在Windows,Android,Linux,Mac下都能正常的使用。
另外Cipher实例化时,模式一定得选CBC模式,如果选择ECB模式,否则在某些平台无法正常使用,测试了在Mac平台下会报java.security.InvalidAlgorithmParameterException: ECB mode cannot use IV 异常。
为此顺带了解了下ECB和CBC模式,ECB是一种字符串分割方式,是加密方式通常采用的一种分割方式,主要是DES等加密方式采用这种方式。
而AES 下的CBC模式则是比ECB模式下衍生出来的一种模式。
CBC这种操作模式,它是在ECB加密的密文的每个数据块进行异或运算与下一个明文块进行加密,从而使所有的块依赖于以前的所有块。这意味着,为了找到一个特定块的明文,则需要知道的密文,密钥和密文对前块。要被加密的第一数据块没有先前的密文,所以明文异或与所谓的初始化向量的64位数字,或IV的简称。因此,如果数据传输通过网络或电话线,有一个传输错误(添加或删除位元) ,该错误将被结转到所有后续块,因为每个块是取决于最后。如果该位被修改只是在运输过程中(这是比较常见的情况下)的错误,只会影响到所有在更改块的位,并在下面的块中的相应位。该错误不传播任何进一步。这种操作模式是比ECB更安全的,因为额外的异或步骤加上一个更多层的加密处理。