项目中需要和C++做数据交互,所有的数据都是使用AES加密,然后base64编码的,现在把代码记录下来下次好参考:
/**
* 功能描述: 解密
*
* @param:
* @return:
* @auther: PC_gongyiyang
* @date: 2018/11/1 17:25
*/
public static String decrypt(String key, String encrypted) {
try {
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
IvParameterSpec iv = new IvParameterSpec(new byte[cipher.getBlockSize()]);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);
byte[] result = Base64.decodeBase64(encrypted);
byte[] original = cipher.doFinal(result);
return new String(original);
} catch (Exception ex) {
log.error(ex.getMessage());
}
return null;
}
/**
* 功能描述: 加密
*
* @param:
* @return:
* @auther: PC_gongyiyang
* @date: 2018/11/1 17:26
*/
public static byte[] encrypt(String key, String value) {
try {
Integer length = 16;
Integer count = value.getBytes().length;
Integer residue = count % length;
if (residue != 0) {
Integer add = length - residue;
for (int i = 0; i < add; i++) {
value = value + '\0';
}
}
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
IvParameterSpec iv = new IvParameterSpec(new byte[cipher.getBlockSize()]);
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.encodeBase64(encrypted);
} catch (Exception ex) {
log.error(ex.getMessage());
}
return new byte[0];
}C++那边如果没有设置的话默认的填充模式应该是NoPadding;nopadding的数据都是16个字节,必须是16的整数倍;所以在字符不足16的整数倍是用'\0'来填充,'\0'在C++里面是null默认不会被解析;
还有关于iv偏移量的问题;C++默认的偏移量应该是16个'\0';就是16位,java也可以设置16个字符:
char[] ivChar = new char[]{'\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',};用16个字符手动设置偏移量也是没问题的;
另外在加密数据传输给C++的时候尽量使用byte原始数据,因为java的byte和string互相转化时可能会涉及到编码问题导致数据发生变化;
版权声明:本文为sinat_21184471原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。