AES+RSA加密解密(js和java互通)

客户端和服务端数据加解密流程图

这里写图片描述

案例

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加密算法

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值