1、客户端生成aes秘钥
js
function getAesKey(len) {
len = len || 32;
var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678'; /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
var maxPos = $chars.length;
var keyStr = '';
for(i = 0; i < len; i++) {
keyStr += $chars.charAt(Math.floor(Math.random() * maxPos));
}
return keyStr;
}
2、客户端生成公钥
js
var pubKey = new RSAKeyPair(public_exponent, "", modulus);
//生成公钥,这里的public_exponent和modulus是从服务端获取,便于服务端可以定时更新公钥
3、 客户端aesKey转成base64
js
var keyStr64 = encode64(keyStr);
4、客户端生成RSA公钥
js
setMaxDigits(130);//BigInt.js
var pubKey = new RSAKeyPair(public_exponent, "", modulus); //获得rsa公钥
5、用公钥加密AES密钥
js
var aesKeyMi = encryptedString(pubKey, keyStr64, RSAAPP.NoPadding, RSAAPP.NumericEncoding);
//此处的keyStr64是AES密钥转成base64后的值
6、用客户端生成的AES密钥加密入参
js
var msg_source = "0102030405060708";
//此处的iv向量和服务端保持一致
var iv = CryptoJS.enc.Utf8.parse(msg_source);
tool.encrypt = function(data) {
//AES加密
var key = CryptoJS.enc.Utf8.parse(keyStr);
var srcs = CryptoJS.enc.Utf8.parse(data);
var encrypted = CryptoJS.AES.encrypt(srcs, key, {
iv: iv,
mode: CryptoJS.mode.CBC
});
return encrypted;
}
7、客户端的入参形式
{"key":aesKeyMi,"param":"此处为加密后的参数"}
8、服务端获取AES密钥
java
/**
* 私钥解密
*
* @param key 接口入参的key
* @return
* @throws Exception
*/
public static String getKey(String key) throws Exception {
//获取经过rsa非对称加密的 客户端生成的aes密钥
if(StringUtils.nullOrBlank(key)) {
return "";
}
RSAPrivateKey privateKey = null;
try {
String privateExponentStr = ENVUtils.getPrivateExponent();//本案例中的privateExponentStr通过配置文件设置
String modulusStr = ENVUtils.getModulus();//本案例中的modulusStr通过配置文件设置
BigInteger modulus = new BigInteger(new String(Base64.decodeBase64(modulusStr), "UTF-8"), 16);
BigInteger privateExponent = new BigInteger(new String(Base64.decodeBase64(privateExponentStr), "UTF-8"), 16);
privateKey = RSAUtils.getPrivateKey(modulus, privateExponent);
return RSAUtils.decryptByPrivateKey(key, privateKey);
}catch(Exception e) {
logger.error("获取私钥失败", e);
return "";
}
}
RSAUtils相关代码
public static RSAPrivateKey getPrivateKey(BigInteger modulus, BigInteger exponent) {
try {
KeyFactory keyFactory = KeyFactory.getInstance("RSA", RSA_RPOVIDER);
RSAPrivateKeySpec keySpec = new RSAPrivateKeySpec(modulus, exponent);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
} catch (Exception e) {
logger.error("合成私钥异常", e);
return null;
}
}
/**
* 私钥解密
*
* @param data
* @param privateKey 私钥
* @return
* @throws Exception
*/
public static String decryptByPrivateKey(String data, RSAPrivateKey privateKey) throws Exception {
Cipher cipher = Cipher.getInstance("RSA/ECB/NoPadding", RSA_RPOVIDER);
cipher.init(Cipher.DECRYPT_MODE, privateKey);
// 模长
int key_len = privateKey.getModulus().bitLength() / 8;
byte[] b = StringUtils.decodeHex(data);
// 如果密文长度大于模长则要分组解密
String ming = "";
byte[][] arrays = splitArray(b, key_len);
for (byte[] arr : arrays) {
ming += new String(cipher.doFinal(arr));
}
return ming;
}
9、服务端用AES密钥解密入参param、
java
public static String aesDecrypt(String encryptStr, String decryptKey)
throws Exception {
if(StringUtils.nullOrBlank(decryptKey)) {
return encryptStr;
}
return aesDecryptByBytes(
base64Decode(encryptStr), decryptKey);
}
public static String aesDecryptByBytes(byte[] encryptBytes,
String decryptKey) throws Exception {
byte[] keys = base64Decode(decryptKey);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//此处的部位方式应该跟客户端保持一致CryptoJS.mode.CBC
IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());//此处的向量应该跟客户端保持一致0102030405060708
cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(keys, "AES"), iv);
byte[] decryptBytes = cipher.doFinal(encryptBytes);
return new String(decryptBytes, "utf-8");
}
public static byte[] base64Decode(String base64Code) throws Exception {
return base64Code == null ? null : Base64.decodeBase64(base64Code);
}
10、服务端处理完业务后,返回加密的数据
java
public static String aesEncrypt(String content, String encryptKey)
throws Exception {
if(StringUtils.nullOrBlank(encryptKey)) {
return content;
}
return base64Encode(aesEncryptToBytes(content, encryptKey));
}
public static byte[] aesEncryptToBytes(String content, String encryptKey)
throws Exception {
byte[] keys = base64Decode(encryptKey);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");//此处的部位方式应该跟客户端保持一致CryptoJS.mode.CBC
IvParameterSpec iv = new IvParameterSpec("0102030405060708".getBytes());//此处的向量应该跟客户端保持一致0102030405060708
cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(keys, "AES"), iv);
return cipher.doFinal(content.getBytes("utf-8"));
}
public static String base64Encode(byte[] bytes) {
return Base64.encodeBase64String(bytes);
}
11、客户端解密出参dataMi
js
//AES解密
var msg_source = "0102030405060708";
//此处的iv向量和服务端保持一致
var iv = CryptoJS.enc.Utf8.parse(msg_source);
tool.decrypt = function(data) {
var key = CryptoJS.enc.Utf8.parse(aesKey);
var decrypt = CryptoJS.AES.decrypt(data, key, {
iv: iv,
mode: CryptoJS.mode.CBC
});
var rtnStr = CryptoJS.enc.Utf8.stringify(decrypt).toString();
mConsole("11111" + rtnStr);
return rtnStr;
}
附上本文需要用到的[js文件和jar(主要是jdk自带包)包]
(http://download.csdn.net/download/qq_18837459/9898084)
PS:我已经备注了下载文件只有jar包和js文件,java代码在上面例子里面已经有了,自己看一下就懂了,觉得需要给一个完整demo才行的,请慎下。
http://www.ohdave.com/rsa/ javascript的rsa加密算法