AES方式加解密
高级加密标准(Advanced Encryption Standard),对称秘钥加密算法之一。
对称加密,就是加密与揭秘用相同的密钥;非对称加密,公钥用于加密,私钥用于解谜数据。
1.需要用到密钥,密钥位数(默认256位).
2.秘钥的存储,如果秘钥存储在本地,通过反编译有可能被其他人获取.
解决办法:
1.用时从server端获取。
2.对秘钥加密后存储在本地,使用时再次的解密(还是会被破解,只是增加了破解的难度)。
3.加解密效率,如果对大文件整个文件加密,花费比较长的时间.
对于小于64KB的文件进行全加密,大于64KB的文件假面文件的前64KB内容,这样提高加密效率。
4.判断文件加密
为了能区分哪些文件加过密,避免二次加密造成的混乱,加密过的文件头部会写入八 个字符"^%!_$#@*"(已加密标示字符串)加以区分,该字符可自行定义.
下面代码使用第二种方法存储密钥,避免从server获取。
/**
*返回Cipher对象,文件加密解密使用到的对象
*ketCode:秘钥
*paramMode:加解密模式标识
*/
private Cipher getEncryptModeCipher(String keyCode, int paramMode) throws Exception {
//该对象用于解密秘钥
PackUtil packUtil = new PackUtil();
//这里其实就是字符串“AES”,故弄玄虚增加破解解密的难度
String algorithm = packUtil.decrypt(ALGORITHM);
//创建一个秘钥规范对象,第一个参数为秘钥,第二个参数为算法,我们选用的是AES算法
SecretKeySpec skeySpec = new SecretKeySpec(packUtil.decrypt(keyCode).getBytes(), algorithm);//
// 创建密钥空间
Cipher cipher = Cipher.getInstance(algorithm);
//以下调用初始化方法指定操作模式,加密 or 解密
switch (paramMode) {
case ENCRY_FLAG:
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
break;
case DECRY_FALG:
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
break;
default:
break;
}
return cipher;
}
小于64K的文件,全部加密,加密后文件头部分内容为“^%!_$#@*”
FileInputStream input = new FileInputStream(fileIn);
FileOutputStream fos = new FileOutputStream(fileOut);
//文件可读字节数,总大小
int availableSize = input.available();
if (availableSize < 64 * 1024) {
byte[] inBytes = new byte[availableSize]
//向文件写入已加密的标示内容,可自行定义内容,与判断时一致即可
fos.write("^%!_$#@*");
int inLength = 0;
//一次性读取文件的全部内容
if ((inLength = input.read(inBytes)) != -1){
//调用加密的接口传入内容参数
byte[] outBytes = cipher.doFinal(inBytes, 0, inLength);
//加密后的内容写入文件中
fos.write(outBytes);
}
}
fos.flush();
fos.close();
input.close();
大于64KB的文件,加密文件前64KB内容,加密后文件头部分内容为“^%!_$#@*”
int blockSize = 64 * 1024;
byte[] inBytes = new byte[blockSize];
//读取文件前64KB大小
int inLength = input.read(inBytes);
fos.write("^%!_$#@*");
//调用加密接口,传入文件内容参数
byte[] outBytes = cipher.doFinal(inBytes);
//加密后的内容写入到文件中
fos.write(outBytes, 0, outBytes.length);
//剩余的未加密的内容依次写入到文件中
byte[] bytes = new byte[100 * 1024];
while ((inLength = input.read(bytes)) != -1) {
fos.write(bytes, 0, inLength);
}
fos.flush();
fos.close();
input.close();
判断文件是否已加密
/**
*判断文件是否加密
*@param filePath 文件路径
*@return true 已加密 false 未加密
*@throws Exception
*/
public boolean isFileEncryption(String filePath) throws Exception {
boolean bool = false;
File file = new File(filePath);
if (file.isFile()) {
InputStream is = new FileInputStream(file);
byte[] byt = new byte[8];
//读取文件头部的已加密标示
is.read(byt);
is.close();
String k = new String(byt);
//这里的已加密标示"^%!_$#@*"与之前写入的要保持一致
bool = ("^%!_$#@*".compareTo(k) == 0);
}
return bool;
}
小于64KB文件解密,需要完全解密
FileInputStream input = new FileInputStream(fileIn);
FileOutputStream fos = new FileOutputStream(fileOut);
int availableSize = input.available();
if (availableSize < 64 * 1024) {
//跳过文件头部的已加密标示字符串“^%!_$#@*”
input.skip(8);
//重新获取input大小
availableSize = input.available();
//读取的内容大小
byte[] inBytes = new byte[availableSize];
int inLength = 0;
if ((inLength = input.read(inBytes)) != -1){
//调用解密接口,与加密接口一样,cipher初始化的时候指定了操作模式
byte[] outBytes = cipher.doFinal(inBytes, 0, inLength);
//解密后的内容写入到文件中
fos.write(outBytes);
}
}
fos.flush();
fos.close();
input.close();
大于64KB文件的解密,解密文件前64KB,为加密的依次读取出来。
//跳过文件头部的已加密标示字符串“^%!_$#@*”
input.skip(8);
//重新获取input大小
int availableSize = input.available();
//解密的内容大小
byte[] inBytes = new byte[availableSize];
//读取加密的内容
int inLength = input.read(inBytes);
if (inLength <= 64*1024) {
//调用解密的接口传入加密的内容
byte[] outBytes = cipher.doFinal(inBytes);
//解密的内容写入到文件中
fos.write(outBytes, 0, outBytes.length);
}
//把未加密的内容依次写入文件中
while ((inLength = input.read(bytes)) != -1) {
fos.write(bytes, 0, inLength);
}
fos.flush();
fos.close();
input.close();
加密解密接口的说明:
/**
*处理 input 缓冲区中从 inputOffset 开始(包含)的前 inputLen 个字节
*/
public final byte[] doFinal (byte[] input, int inputOffset, int inputLen) throws
IllegalBlockSizeException, BadPaddingException
/**
*处理 input 缓冲区中的字节
*/
public final byte[] doFinal (byte[] input) throws
IllegalBlockSizeException, BadPaddingException
Cipher类API参考