Node.js中AES加密和其它语言不一致问题解决办法


Posted in Javascript onMarch 10, 2014

例子一:

这几天被一个问题困扰着。Nodejs的AES加密和Java,C#加密出来的不一致。当然,这样就不能解密了。纠结了许久:后来还是实在不行了,看了下源代码,要不然还得继续纠结下去。网上说,通常的nodejs AES和其他语言实现不一样。好吧~~或许吧。
nodejs的crypto模块。

var crypto = require('crypto');
    var data = "156156165152165156156";
    console.log('Original cleartext: ' + data);
    var algorithm = 'aes-128-ecb';
    var key = '78541561566';
    var clearEncoding = 'utf8';
    //var cipherEncoding = 'hex';
    //If the next line is uncommented, the final cleartext is wrong.
    var cipherEncoding = 'base64';
/*加密*/
    var cipher = crypto.createCipher(algorithm, key);
    var cipherChunks = [];
    cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
    cipherChunks.push(cipher.final(cipherEncoding));
    console.log(cipherEncoding + ' ciphertext: ' + cipherChunks.join(''));
/*解密*/
    var decipher = crypto.createDecipher(algorithm, key);
    var plainChunks = [];
    for (var i = 0;i < cipherChunks.length;i++) {
      plainChunks.push(decipher.update(cipherChunks[i], cipherEncoding, clearEncoding));
    }
    plainChunks.push(decipher.final(clearEncoding));
    console.log("UTF8 plaintext deciphered: " + plainChunks.join(''));

的确,没错~~加密解密成功。但是和java,C#中加密出来的不一样啊。神啊。我想,大家都在这里纠结着吧~~对不对。其实只要加个向量,就可以和一致了。网上搜索出来的资源太少。才让自己纠结那么久。好吧,正确代码是:
var crypto = require('crypto');
    var data = "156156165152165156156";
    console.log('Original cleartext: ' + data);
    var algorithm = 'aes-128-ecb';
    var key = '78541561566';
    var clearEncoding = 'utf8';
    var iv = "";
    //var cipherEncoding = 'hex';
    //If the next line is uncommented, the final cleartext is wrong.
    var cipherEncoding = 'base64';
    var cipher = crypto.createCipheriv(algorithm, key,iv);
    var cipherChunks = [];
    cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
    cipherChunks.push(cipher.final(cipherEncoding));
    console.log(cipherEncoding + ' ciphertext: ' + cipherChunks.join(''));
    var decipher = crypto.createDecipheriv(algorithm, key,iv);
    var plainChunks = [];
    for (var i = 0;i < cipherChunks.length;i++) {
      plainChunks.push(decipher.update(cipherChunks[i], cipherEncoding, clearEncoding));
    }
    plainChunks.push(decipher.final(clearEncoding));
    console.log("UTF8 plaintext deciphered: " + plainChunks.join(''));

对比发现,加密出来是一致的。好吧,结贴~~~我恨你,浪费了我一天时间。

例子二:

工作中遇到nodejs端通过aes加密,安卓客户端java解密,同意nodejs也需要解密安卓客户端加密过来的内容,发现两个加密结果不一样,查询资料发现java端需要对密钥za再MD5加密一遍,以下是aes ecb加密的内容,如果是cbc也同样需要对秘钥MD5加密:

nodejs:

/** 
 * aes加密 
 * @param data 
 * @param secretKey 
 */  
encryptUtils.aesEncrypt = function(data, secretKey) {  
    var cipher = crypto.createCipher('aes-128-ecb',secretKey);  
    return cipher.update(data,'utf8','hex') + cipher.final('hex');  
}  /** 
 * aes解密 
 * @param data 
 * @param secretKey 
 * @returns {*} 
 */  
encryptUtils.aesDecrypt = function(data, secretKey) {  
    var cipher = crypto.createDecipher('aes-128-ecb',secretKey);  
    return cipher.update(data,'hex','utf8') + cipher.final('utf8');  
} 

java:
package com.iofamily.util;  import java.security.MessageDigest;  
import javax.crypto.Cipher;  
import javax.crypto.spec.SecretKeySpec;  
/** 
 * AES加密,与Nodejs 保持一致 
 * @author lmiky 
 * @date 2014-2-25 
 */  
public class AESForNodejs {  
    public static final String DEFAULT_CODING = "utf-8";  
    /** 
     * 解密 
     * @author lmiky 
     * @date 2014-2-25 
     * @param encrypted 
     * @param seed 
     * @return 
     * @throws Exception 
     */  
    private static String decrypt(String encrypted, String seed) throws Exception {  
        byte[] keyb = seed.getBytes(DEFAULT_CODING);  
        MessageDigest md = MessageDigest.getInstance("MD5");  
        byte[] thedigest = md.digest(keyb);  
        SecretKeySpec skey = new SecretKeySpec(thedigest, "AES");  
        Cipher dcipher = Cipher.getInstance("AES");  
        dcipher.init(Cipher.DECRYPT_MODE, skey);  
        byte[] clearbyte = dcipher.doFinal(toByte(encrypted));  
        return new String(clearbyte);  
    }  
    /** 
     * 加密 
     * @author lmiky 
     * @date 2014-2-25 
     * @param content 
     * @param key 
     * @return 
     * @throws Exception 
     */  
    public static String encrypt(String content, String key) throws Exception {  
        byte[] input = content.getBytes(DEFAULT_CODING);  
        MessageDigest md = MessageDigest.getInstance("MD5");  
        byte[] thedigest = md.digest(key.getBytes(DEFAULT_CODING));  
        SecretKeySpec skc = new SecretKeySpec(thedigest, "AES");  
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");  
        cipher.init(Cipher.ENCRYPT_MODE, skc);  
        byte[] cipherText = new byte[cipher.getOutputSize(input.length)];  
        int ctLength = cipher.update(input, 0, input.length, cipherText, 0);  
        ctLength += cipher.doFinal(cipherText, ctLength);  
        return parseByte2HexStr(cipherText);  
    }  
    /** 
     * 字符串转字节数组 
     * @author lmiky 
     * @date 2014-2-25 
     * @param hexString 
     * @return 
     */  
    private static byte[] toByte(String hexString) {  
        int len = hexString.length() / 2;  
        byte[] result = new byte[len];  
        for (int i = 0; i < len; i++) {  
            result[i] = Integer.valueOf(hexString.substring(2 * i, 2 * i + 2), 16).byteValue();  
        }  
        return result;  
    }  
    /** 
     * 字节转16进制数组 
     * @author lmiky 
     * @date 2014-2-25 
     * @param buf 
     * @return 
     */  
    private static String parseByte2HexStr(byte buf[]) {  
        StringBuffer sb = new StringBuffer();  
        for (int i = 0; i < buf.length; i++) {  
            String hex = Integer.toHexString(buf[i] & 0xFF);  
            if (hex.length() == 1) {  
                hex = '0' + hex;  
            }  
            sb.append(hex);  
        }  
        return sb.toString();  
    }  
    public static void main(String[] args) throws Exception {  
        System.out.println(AESForNodejs.encrypt("fsadfsdafsdafsdafsadfsadfsadf", "1234fghjnmlkiuhA"));  
        System.out.println(AESForNodejs.decrypt("5b8e85b7a86ad15a275a7cb61fe4c0606005e8741f68797718a3e90d74b5092a", "1234fghjnmlkiuhA"));  
    }  
}
Javascript 相关文章推荐
How to Auto Include a Javascript File
Feb 02 Javascript
Ext.FormPanel 提交和 Ext.Ajax.request 异步提交函数的区别
Nov 12 Javascript
ExtJs中简单的登录界面制作方法
Aug 19 Javascript
javascript判断复选框是否选中的方法
Oct 16 Javascript
省市选择的简单实现(基于zepto.js)
Jun 21 Javascript
javascript简单实现等比例缩小图片的方法
Jul 27 Javascript
javascript验证内容为数字以及长度为10的简单实例
Aug 20 Javascript
BootStrapTable 单选及取值的实现方法
Jan 10 Javascript
angularjs中的$eval方法详解
Apr 24 Javascript
Vue列表页渲染优化详解
Jul 24 Javascript
jQuery+CSS实现的table表格行列转置功能示例
Jan 08 jQuery
vue-treeselect的基本用法以及解决点击无法出现拉下菜单
Apr 30 Vue.js
JS中的构造函数详细解析
Mar 10 #Javascript
node.js使用nodemailer发送邮件实例
Mar 10 #Javascript
php中给js数组赋值方法
Mar 10 #Javascript
javascript操作referer详细解析
Mar 10 #Javascript
JS数组的赋值介绍
Mar 10 #Javascript
JS删除字符串中重复字符方法
Mar 09 #Javascript
用JavaScript实现类似于ListBox功能示例代码
Mar 09 #Javascript
You might like
php下批量挂马和批量清马代码
2011/02/27 PHP
计算php页面运行时间的函数介绍
2013/07/01 PHP
Win7 64位系统下PHP连接Oracle数据库
2014/08/20 PHP
PHP 验证登陆类分享
2015/03/13 PHP
phpcms手机内容页面添加上一篇和下一篇
2015/06/05 PHP
关于php中一些字符串总结
2016/05/05 PHP
php格式文件打开的四种方法
2018/02/24 PHP
Yii2.0框架实现带分页的多条件搜索功能示例
2019/02/20 PHP
用javascript实现在小方框中浏览大图的代码
2007/08/14 Javascript
2010年最佳jQuery插件整理
2010/12/06 Javascript
Javascript 多浏览器兼容总结(实战经验)
2013/10/30 Javascript
根据表格中的某一列进行排序的javascript代码
2013/11/29 Javascript
Mac OS X 系统下安装和部署Egret引擎开发环境
2014/09/03 Javascript
原生js实现键盘控制div移动且解决停顿问题
2016/12/05 Javascript
使用Dropzone.js上传的示例代码
2017/10/10 Javascript
AngularJS 应用模块化的使用
2018/04/04 Javascript
vue安装和使用scss及sass与scss的区别详解
2018/10/15 Javascript
Vue + Element UI图片上传控件使用详解
2019/08/20 Javascript
layui复选框的全选与取消实现方法
2019/09/02 Javascript
JS动态显示倒计时效果
2019/12/12 Javascript
JS代码触发事件代码实例
2020/01/02 Javascript
在webstorm中配置less的方法详解
2020/09/25 Javascript
Python进阶之尾递归的用法实例
2018/01/31 Python
Python处理文本换行符实例代码
2018/02/03 Python
pandas DataFrame数据转为list的方法
2018/04/11 Python
在django中实现页面倒数几秒后自动跳转的例子
2019/08/16 Python
python支付宝支付示例详解
2019/08/22 Python
python 矢量数据转栅格数据代码实例
2019/09/30 Python
Django中modelform组件实例用法总结
2020/02/10 Python
htnl5利用svg页面高斯模糊的方法
2018/07/20 HTML / CSS
美国酒店控股公司:Choice Hotels
2018/06/15 全球购物
酒店人事专员岗位职责
2013/12/19 职场文书
离婚协议书范本(2014版)
2014/09/28 职场文书
2014年银行个人工作总结
2014/12/05 职场文书
党员民主生活会材料
2014/12/15 职场文书
浅谈pytorch中stack和cat的及to_tensor的坑
2021/05/20 Python