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 相关文章推荐
JS提交并解析后台返回的XML的代码
Nov 03 Javascript
script的async属性以非阻塞的模式加载脚本
Jan 15 Javascript
解析jQuery的三种bind/One/Live事件绑定使用方法
Dec 30 Javascript
理解javascript中的回调函数(callback)
Sep 02 Javascript
基于Bootstrap重置输入框内容按钮插件
May 12 Javascript
jQuery实现的右下角广告窗体跟随效果示例
Sep 16 Javascript
有趣的bootstrap走动进度条
Dec 01 Javascript
javascript-解决mongoose数据查询的异步操作
Dec 22 Javascript
使用JavaScript为一张图片设置备选路径的方法
Jan 04 Javascript
详解Vue使用 vue-cli 搭建项目
Apr 20 Javascript
利用vue.js实现被选中状态的改变方法
Feb 08 Javascript
利用JavaScript缓存远程窃取Wi-Fi密码的思路详解
Nov 05 Javascript
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
PHPwind整合最土系统用户同步登录实现方法
2010/12/08 PHP
PHP文件缓存smarty模板应用实例分析
2016/02/26 PHP
JQuery CSS样式控制 学习笔记
2009/07/23 Javascript
javascript+mapbar实现地图定位
2010/04/09 Javascript
利用location.hash实现跨域iframe自适应
2010/05/04 Javascript
event.currentTarget与event.target的区别介绍
2012/12/31 Javascript
输入自动提示搜索提示功能的javascript:sugggestion.js
2013/09/02 Javascript
Javascript实现滚动图片新闻的实例代码
2013/11/27 Javascript
JavaScript用Number方法实现string转int
2014/05/13 Javascript
jQuery实现返回顶部效果的方法
2015/05/29 Javascript
js控制多图左右滚动切换效果代码分享
2015/08/26 Javascript
js代码实现点击按钮出现60秒倒计时
2021/01/28 Javascript
JQuery datepicker 用法详解
2015/12/25 Javascript
基于vue.js实现图片轮播效果
2016/12/01 Javascript
JS 插件dropload下拉刷新、上拉加载使用小结
2017/04/13 Javascript
浅谈Webpack 是如何加载模块的
2018/05/24 Javascript
ES6入门教程之Array.from()方法
2019/03/23 Javascript
新手入门js闭包学习过程解析
2019/10/08 Javascript
python 远程统计文件代码分享
2015/05/14 Python
Python实现定时任务
2017/02/08 Python
python使用tkinter实现简单计算器
2018/01/30 Python
python实现录音小程序
2020/10/26 Python
Python数组并集交集补集代码实例
2020/02/18 Python
Laura Geller官网:美国彩妆品牌
2018/12/29 全球购物
北美最大的零售退货翻新商:VIP Outlet
2019/11/21 全球购物
重写子类方法时,抛出异常的书写注意事项
2015/10/17 面试题
解释i节点在文件系统中的作用
2013/11/26 面试题
实习生单位鉴定意见
2013/12/04 职场文书
上班早退检讨书
2014/01/09 职场文书
酒店中秋节活动方案
2014/01/31 职场文书
考核工作实施方案
2014/03/30 职场文书
空乘英文求职信
2014/04/13 职场文书
红领巾心向党演讲稿
2014/09/10 职场文书
推广普通话宣传标语口号
2015/12/26 职场文书
python使用openpyxl库读写Excel表格的方法(增删改查操作)
2021/05/02 Python
springboot用户数据修改的详细实现
2022/04/06 Java/Android