用户登陆的验证信息需要与前端互传,采用一种简单的加密手段。在开发过程中很快实现了与安卓的加密互通,但与ios的打通踩到个大坑, 详见代码中的注释和文后的链接。
有怀疑到加密位数的问题,java如果要使用256位的密钥要修改基础jar包,最终没有采用。
(Java本身限制密钥的长度最多128位,而AES256需要的密钥长度是256位,因此需要到Java官网上下载一个Java Cryptography Extension (JCE) Unlimited Strength Jurisdiction Policy Files。在Java SE的下载页面下面的Additional Resources那里会有下载链接。下载后打开压缩包,里面有两个jar文件。把这两个jar文件解压到JRE目录下的lib/security文件夹,覆盖原来的文件。这样Java就不再限制密钥的长度了。)
package cipher;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class AESCodeUtil {
/**
* 密钥,必须16位
*/
private static final String IV_STRING = "1234567890abcdef";
private static Base64 base64 = new Base64();
private static String encryptAES(String content, String key)
throws Exception {
byte[] byteContent = content.getBytes("UTF-8");
// 注意,为了能与 iOS 统一
// 这里的 key 不可以使用 KeyGenerator、SecureRandom、SecretKey 生成
byte[] enCodeFormat = key.getBytes();
SecretKeySpec secretKeySpec = new SecretKeySpec(enCodeFormat, "AES");
byte[] initParam = IV_STRING.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
// 指定加密的算法、工作模式和填充方式
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);
byte[] encryptedBytes = cipher.doFinal(byteContent);
return new String(base64.encode(encryptedBytes));
}
private static String decryptAES(String content, String key)
throws Exception {
byte[] encryptedBytes = base64.decode(content);
byte[] enCodeFormat = key.getBytes();
SecretKeySpec secretKey = new SecretKeySpec(enCodeFormat, "AES");
byte[] initParam = IV_STRING.getBytes();
IvParameterSpec ivParameterSpec = new IvParameterSpec(initParam);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
byte[] result = cipher.doFinal(encryptedBytes);
return new String(result, "UTF-8");
}
/**
* 用于加密
* @param content
* @return
*/
public static String base64convert(String content){
String str1 = content.replaceAll("/", "_");
return str1.replaceAll("\\+", "-");
}
/**
* 用于解密
* @param content
* @return
*/
public static String base64convert2(String content){
String str1 = content.replaceAll("-", "\\+");
return str1.replaceAll("_", "/");
}
private static String encode(String content, String key){
try {
return base64convert(encryptAES(content,key));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
private static String decode(String content, String key){
try {
return decryptAES(base64convert2(content), key);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decode(String code){
return decode(code,IV_STRING);
}
public static String encode(String code){
return encode(code,IV_STRING);
}
public static void main(String[] args) {
String content = "code_12345678901234567890";
String coded = encode(content);
System.out.println("密文:" + coded);
String origin = decode(coded);
System.out.println("原文:" + origin);
}
}
另附两个别人踩坑的经历
http://dditblog.com/itshare_603.html
http://www.cnblogs.com/mantgh/p/4244891.html