使用AES加密时,当密钥大于128时,代码会抛出java.security.InvalidKeyException: Illegal key size or default parameters
。网上大部分的解决方法都是下载相关的jar包,覆盖掉${java_home}/jre/lib/security/ 下面的local_policy.jar和US_export_policy.jar来解除这种限制。但有时候,在生产环境中不能或不方便进行这种覆盖操作,这时候可以在加解密代码中加上下列代码去掉这种限制:
//使其支持256位秘钥
static {
Field field = null;
try {
field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception e) {
e.printStackTrace();
}
}
顺便提供一个文件加解密的类FileAesEncryptUtil.java
package com.learn;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.io.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.security.GeneralSecurityException;
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
public class FileAesEncryptUtil {
//可修改成配置,SECRET根据实际修改
private final static String SECRET = "JXU4RkQ5JXU5MUNDJXU2NjJGJXU4OTgxJXU1MkEwJXU1QkM2JXU3Njg0JXU1MTg1JXU1QkI5JXVGRjAx";
private final static String AES = "AES";
private final static String AESArgs = "AES/ECB/PKCS5Padding";
//使其支持256位秘钥
static {
Field field = null;
try {
field = Class.forName("javax.crypto.JceSecurity").getDeclaredField("isRestricted");
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, java.lang.Boolean.FALSE);
} catch (Exception e) {
e.printStackTrace();
}
}
//生成256位的秘钥
private static SecretKey generateAesSecretKey() {
try {
KeyGenerator keygen = KeyGenerator.getInstance(AES);
SecureRandom sha1PANG = SecureRandom.getInstance("SHA1PRNG");
sha1PANG.setSeed(SECRET.getBytes());
keygen.init(256, sha1PANG);
return keygen.generateKey();
} catch (NoSuchAlgorithmException e) {
throw new RuntimeException(e);
}
}
//加密解密流文件
private static void crypt(InputStream in, OutputStream out, Cipher cipher) throws IOException, GeneralSecurityException {
int blockSize = cipher.getBlockSize() * 1000;
int outputSize = cipher.getOutputSize(blockSize);
byte[] inBytes = new byte[blockSize];
byte[] outBytes = new byte[outputSize];
int inLength = 0;
boolean more = true;
while (more) {
inLength = in.read(inBytes);
if (inLength == blockSize) {
int outLength = cipher.update(inBytes, 0, blockSize, outBytes);
out.write(outBytes, 0, outLength);
} else {
more = false;
}
}
if (inLength > 0)
outBytes = cipher.doFinal(inBytes, 0, inLength);
else
outBytes = cipher.doFinal();
out.write(outBytes);
}
//加密
public static void encodeFile(File srcFile, File destFile) throws IOException, GeneralSecurityException {
// 获取cipher对象 用于加密解密
Key key = generateAesSecretKey();
Cipher cipher = Cipher.getInstance(AESArgs);
cipher.init(Cipher.ENCRYPT_MODE, key); // 加密是为ENCRYPT_MODE
InputStream is = new FileInputStream(srcFile);
OutputStream os = new FileOutputStream(destFile);
crypt(is, os, cipher);
os.close();
is.close();
}
//解密
public static void decodeAES(File srcFile, File destFile) throws IOException, GeneralSecurityException {
// 获取cipher对象 用于加密解密
Key key = generateAesSecretKey();
Cipher cipher = Cipher.getInstance(AESArgs);
cipher.init(Cipher.DECRYPT_MODE, key); // 解密是为DECRYPT_MODE
InputStream is = new FileInputStream(srcFile);
OutputStream os = new FileOutputStream(destFile);
crypt(is, os, cipher);
os.close();
is.close();
}
}
测试
package com.learn;
import java.io.File;
public class App
{
public static void main( String[] args )
{
File src= new File("/test.txt");
File encode= new File("/encode.txt");
File decode=new File("/decode.txt");
try {
FileAesEncryptUtil.encodeFile(src,encode);
FileAesEncryptUtil.decodeAES(encode,decode);
} catch (Exception e) {
e.printStackTrace();
}
}
}
结果