Java 的 AES 加密实现及问题解决
生成密钥
public static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";
private final static String ENCRYPTKEY = "0123456789abcdefghijklmnopqretuvwxyz";
private static SecretKey secretKey = null;
private static void initKey() {
try {
secretKey = generateKey(ENCRYPTKEY.getBytes());
} catch (Exception e) {
e.printStackTrace();
}
}
private static SecretKey generateKey(byte[] secretKey) throws Exception {
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(secretKey);
KeyGenerator kg = null;
try {
kg = KeyGenerator.getInstance("AES");
kg.init(256, secureRandom);
SecretKey skey = kg.generateKey();
byte[] raw = skey.getEncoded();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
return skeySpec;
} catch (NoSuchAlgorithmException e) {
logger.error(e.getMessage(), e);
return null;
}
}
加密实现
public static String encrypt(String input) throws Exception {
if (secretKey == null) {
initKey();
}
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] iv = cipher.getIV();
byte[] encrypt = cipher.doFinal(input.getBytes("utf-8"));
byte[] ret = new byte[iv.length + encrypt.length];
System.arraycopy(encrypt, 0, ret, 0, encrypt.length);
System.arraycopy(iv, 0, ret, encrypt.length, iv.length);
return DatatypeConverter.printBase64Binary(ret);
}
解密实现
public static String decrypt(String input) throws Exception {
if (secretKey == null) {
initKey();
}
byte[] inputBytes = DatatypeConverter.parseBase64Binary(input);
byte[] iv = new byte[16];
byte[] cipherBytes = new byte[inputBytes.length - 16];
System.arraycopy(inputBytes, 0, cipherBytes, 0, cipherBytes.length);
System.arraycopy(inputBytes, cipherBytes.length, iv, 0, 16);
Cipher cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
cipher.init(Cipher.DECRYPT_MODE, secretKey, new IvParameterSpec(iv));
byte[] decrypt = cipher.doFinal(cipherBytes);
return new String(decrypt);
}
问题处理
问题描述
在使用 256 位加密时,控制台报错如下:
java.security.InvalidKeyException: Illegal key size or default parameters
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1026)
at javax.crypto.Cipher.implInit(Cipher.java:801)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1249)
at javax.crypto.Cipher.init(Cipher.java:1186)
这是由于 key 的变更(由原来的 128 位变更为 256 位),导致加密 / 解密的失败。
之所以会出现这种问题,我们就要了解一个新的东西 ——JCE。在 Java 的核心类库中有一个 JCE(Java Cryptography Extension),JCE 是一组包,它们提供用于加密、密钥生成和协商以及 Message Authentication Code(MAC)算法的框架和实现,所以这个是实现加密解密的重要类库。
问题解决
我们要做的就是更换 JCE 的库,该文件位置在你的 JDK/jre/lib/security 目录下面,该目录下我们可以看到两个 jar 包:local_policy.jar,US_export_policy.jar,这两个 jar 包是 jdk 自带的。我们需要下载支持 256 位密钥加密的 jar 包。
- JDK8:
其对应的 JCE 下载地址 - JDK7:
其对应的 JCE 下载地址 - JDK6:
其对应的 JCE 下载地址
下载完后,解压,将其中的 “local_policy.jar” 和 “US_export_policy.jar” 两个文件替换掉自己 % JAVE_HOME%\jre\lib\security 文件夹下对应的原文件(% JAVE_HOME% 是自己电脑的 Java 路径)。
JDK1.8 以上的该目录下压根没有这两个 JAR 包。
针对这种情况,我们的解决方式为:vim 命令打开 java.security 文件,将注释掉的如下配置打开,然后保存即可。
#crypto.policy=unlimited
相关文章