什么是AES加密,可查看博客 :https://blog.csdn.net/chenhuakang/article/details/80223202?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_title-0&spm=1001.2101.3001.4242
需要注意的点有如下:
1、算法的名称与加密时是否相同
2、加密和解密时的模式、填充是否相同
3、加密和解密时的密钥是否相同
4、模式、填充是否是该算法支持的
会出现的问题有
1、InvalidAlgorithmParameterException异常expected IV length of 16 but was 8
解决办法:
/**
* 补码
* aes加密的向量为16位,des加密的向量为8位,当不足时需要补位,否则抛异常。
* 补码 这里不能补"0",要补 "\0",因为在ASCII码中"0"为48,所以需要把0转译,故"\0"才为0。
*
* @param iv
* @return
*/
private static byte[] getIv(String iv) {
StringBuffer buffer = new StringBuffer(16);
buffer.append(iv);
while (buffer.length() < 16) {
buffer.append("\0");
}
if (buffer.length() > 16) {
buffer.setLength(16);
}
return buffer.toString().getBytes();
}
2、javax.crypto.BadPaddingException: error:1e000065:Cipher functions:OPENSSL_internal:BAD_DECRYPT
导致这个问题的原因就是 密钥不对 ,要严格按照密钥的生成规则
解决办法可参考如下: private static final String ALGORITHM = "AES/CBC/PKCS5Padding"; private static final String ENCODING = "utf-8"; private static final String ALGORITHM_AES = "AES"; private static final String KEY = "换成你自己的key"; //密钥 key跟后台协商一个即可,保持一致 private static final String IV = "换成你自己的iv"; // 密钥向量,这里的偏移量也需要跟后台一致,一般跟key一样就行 /** * 加密 * * @param srcData 原数据 * @return * @throws Exception */ public static String encryptAESCBC(String srcData) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM_AES); Cipher cipher = Cipher.getInstance(ALGORITHM); //使用CBC模式必须指定IvParameterSpec,且expected IV length of 16,即长度限制为16 //如果报异常,IV.getBytes()换成第一点中的getIv(IV)方法即可 cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(IV.getBytes())); byte[] encData = cipher.doFinal(srcData.getBytes(ENCODING)); return parseByte2HexStr(encData); } /** * 解密 * * @param encData 需解密数据 * @return * @throws Exception */ public static String decryptAESCBC(String encData) throws Exception { SecretKeySpec keySpec = new SecretKeySpec(KEY.getBytes(), ALGORITHM_AES); Cipher cipher = Cipher.getInstance(ALGORITHM); cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(IV.getBytes())); byte[] decryptData = cipher.doFinal(parseHexStr2Byte(encData)); return new String(decryptData, ENCODING); } /** * 将16进制转换为二进制 * * @param hexStr * @return */ 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; } /** * 将二进制转换成16进制 * * @param buf * @return */ 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(); }
3、javax.crypto.IllegalBlockSizeException: error:1e00007b:Cipher functions:OPENSSL_internal:WRONG_FINAL_BLOCK_LENGTH 报这个问题的解决办法可参考 https://www.cnblogs.com/lsdb/p/9324372.html
4、加解密参考代码:
/**
* 加密
*
* @param srcData 原数据
* @param key 密钥
* @param iv 密钥向量
* @return
* @throws Exception
*/
public static byte[] encryptAESCBC(byte[] srcData, byte[] key, byte[] iv) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM_AES);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv));
byte[] encData = cipher.doFinal(srcData);
return encData;
}
/**
* 解密
*
* @param encData 需解密数据
* @param key 密钥
* @param iv 密钥向量
* @return
* @throws Exception
*/
public static String decryptAESCBC(byte[] encData, byte[] key, byte[] iv) throws Exception {
SecretKeySpec keySpec = new SecretKeySpec(key, ALGORITHM_AES);
Cipher cipher = Cipher.getInstance(ALGORITHM);
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(iv));
return new String(cipher.doFinal(encData), Charset.forName(ENCODING));
}
发生错误时,先确认是否满足了需要注意的点。