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不间断向上滚动效果代码
Dec 25 Javascript
javascript怎么禁用浏览器后退按钮
Mar 27 Javascript
JavaScript判断变量是否为空的自定义函数分享
Jan 31 Javascript
基于jQuery+Cookie实现的防止刷新的在线考试倒计时
Jun 19 Javascript
jquery判断input值不为空的方法
Jun 05 Javascript
解决wx.onMenuShareTimeline出现的问题
Aug 16 Javascript
Bootstrap企业网站实战项目4
Oct 14 Javascript
JS获取本周周一,周末及获取任意时间的周一周末功能示例
Feb 09 Javascript
详解Vue2 无限级分类(添加,删除,修改)
Mar 07 Javascript
浅谈Koa服务限流方法实践
Oct 23 Javascript
JavaScript fetch接口案例解析
Aug 30 Javascript
vue递归获取父元素的元素实例
Aug 07 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
解析linux下安装memcacheq(mcq)全过程笔记
2013/06/27 PHP
php简单日历函数
2015/10/28 PHP
详解WordPress中过滤链接与过滤SQL语句的方法
2015/12/18 PHP
在laravel中使用Symfony的Crawler组件分析HTML
2017/06/19 PHP
Cookie跨域问题解决方案代码示例
2020/11/24 PHP
让getElementsByName适应IE和firefox的方法
2007/09/24 Javascript
jQuery学习笔记之jQuery的DOM操作
2010/12/22 Javascript
Javascript this 的一些学习总结
2012/08/31 Javascript
js判断undefined类型,undefined,null, 的区别详细解析
2013/12/16 Javascript
JS延迟加载加快页面打开速度示例代码
2013/12/30 Javascript
jquery弹窗插件colorbox绑定动态生成元素的方法
2014/06/20 Javascript
jquery访问ashx文件示例代码
2014/08/11 Javascript
全面了解javascript三元运算符
2016/06/27 Javascript
bootstrap table小案例
2016/10/21 Javascript
详解Vue 中 extend 、component 、mixins 、extends 的区别
2017/12/20 Javascript
Node.JS用纯JavaScript生成图片或滑块式验证码功能
2019/09/12 Javascript
在LayUI图片上传中,解决由跨域问题引起的请求接口错误的方法
2019/09/24 Javascript
原生JavaScript实现滑动拖动验证的示例代码
2019/12/06 Javascript
js刷新页面location.reload()用法详解
2019/12/09 Javascript
js生成1到100的随机数最简单的实现方法
2020/02/07 Javascript
Python中datetime常用时间处理方法
2015/06/15 Python
Python中执行存储过程及获取存储过程返回值的方法
2017/10/07 Python
Python中面向对象你应该知道的一下知识
2019/07/10 Python
使用phonegap播放音频的实现方法
2017/03/31 HTML / CSS
html5使用window.postMessage进行跨域实现数据交互的一次实战
2021/02/24 HTML / CSS
小米乌克兰网上商店:Xiaomi.UA
2019/10/29 全球购物
餐厅经理岗位职责和岗位目标
2014/02/13 职场文书
工程采购员岗位职责
2014/03/09 职场文书
小学评语大全
2014/04/22 职场文书
运动会稿件100字
2014/09/24 职场文书
公司领导班子民主生活会对照检查材料
2014/10/02 职场文书
先进事迹材料范文
2014/12/29 职场文书
优秀团员主要事迹材料
2015/11/05 职场文书
总结一些Java常用的加密算法
2021/06/11 Java/Android
python 详解turtle画爱心代码
2022/02/15 Python
python中filter,map,reduce的作用
2022/06/10 Python