前几天,使用AES加密,遇到一奇怪问题,用AES加密,解密后在windows下正常,在Linux中文确会加密成问号,当时才用的是AES/CBC/NoPadding模式,并且进行了base64加解密。
通过多种尝试,均不知道为何。最后确定在AES/CBC/PKCS5Padding模式下和AES/ECB/PKCS5Padding模式下不会出现中文乱码的情况,同时因为ios只有AES/CBC/PKCS7Padding和AES/ECB/PKCS5Padding,在PHP中为zeropadding,所以采用了AES/ECB/PKCS5Padding模式,这样可以解决乱码问题,而且可以在oc,java,php三种语言中通用。但是因为php为zeropadding,我们在设置偏移量时需要把偏移量设置为16个0.来兼容各个版本语言。
下面是在网上找到的java版源码:
public class AES1 {
// /** 算法/模式/填充 **/
private static final String CipherMode ="AES/CBC/PKCS5Padding";
// /** 创建密钥 **/
private static SecretKeySpec createKey(String key) {
byte[] data = null;
if (key == null) {
key ="";
}
StringBuffer sb = new StringBuffer(16);
sb.append(key);
while (sb.length() < 16) {
sb.append("0");
}
if (sb.length() > 16) {
sb.setLength(16);
}
try {
data = sb.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new SecretKeySpec(data,"AES");
}
private static IvParameterSpec createIV(String password) {
byte[] data = null;
if (password == null) {
password ="";
}
StringBuffer sb = new StringBuffer(16);
sb.append(password);
while (sb.length() < 16) {
sb.append("0");
}
if (sb.length() > 16) {
sb.setLength(16);
}
try {
data = sb.toString().getBytes("UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return new IvParameterSpec(data);
}
// /** 加密字节数据 **/
public static byte[] encrypt(byte[] content, String password, String iv) {
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.ENCRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// /** 加密(结果为16进制字符串) **/
public static String encrypt(String content, String password, String iv) {
byte[] data = null;
try {
data = content.getBytes("UTF-8");
} catch (Exception e) {
e.printStackTrace();
}
data = encrypt(data, password, iv);
String result = new Base64().encodeToString(data);
return result;
}
// /** 解密字节数组 **/
public static byte[] decrypt(byte[] content, String password, String iv) {
try {
SecretKeySpec key = createKey(password);
Cipher cipher = Cipher.getInstance(CipherMode);
cipher.init(Cipher.DECRYPT_MODE, key, createIV(iv));
byte[] result = cipher.doFinal(content);
return result;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
// /** 解密 **/
public static String decrypt(String content, String password, String iv) {
byte[] data = null;
try {
data = new Base64().decode(content);//先用base64解密
} catch (Exception e) {
e.printStackTrace();
}
data = decrypt(data, password, iv);
if (data == null)
return null;
String result = null;
try {
result = new String(data,"UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return result;
}
}