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

 更新时间:2014年03月10日 09:33:57   作者:  
这篇文章主要介绍了Node.js中AES加密和其它语言不一致问题解决办法,例如和C#、JAVA语言相互通信时,需要的朋友可以参考下

例子一:

这几天被一个问题困扰着。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")); 
    } 
}

相关文章

  • JS跨域交互(jQuery+php)之jsonp使用心得

    JS跨域交互(jQuery+php)之jsonp使用心得

    JSON是一种基于文本的数据交换方式,或者叫做数据描述格式,这篇文章主要介绍了JS跨域交互(jQuery+php)之jsonp使用心得的相关资料,非常不错,具有参考借鉴价值,需要的朋友一起学习吧
    2016-07-07
  • JavaScript实现星级评分

    JavaScript实现星级评分

    本文主要分享了JavaScript实现星级评分的实例代码,具有一定的参考价值,下面跟着小编一起来看下吧
    2017-01-01
  • JavaScript实现Base64编码转换

    JavaScript实现Base64编码转换

    这篇文章主要介绍了JavaScript实现Base64编码转换的相关资料,非常简单实用,需要的朋友可以参考下
    2016-04-04
  • 5分钟快速看懂ES6中的反射与代理

    5分钟快速看懂ES6中的反射与代理

    这篇文章主要给大家介绍了如何通过5分钟快速看懂ES6中的反射与代理的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用ES6具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-12-12
  • Javascript 八进制转义字符(8进制)

    Javascript 八进制转义字符(8进制)

    最近在看一些Javascript玩魔术的资料,感叹那些真正的是在玩技术,相当让人佩服。
    2011-04-04
  • JavaScript实现LRU算法的示例详解

    JavaScript实现LRU算法的示例详解

    不知道屏幕前的朋友们,有没有和我一样,觉得LRU算法原理很容易理解,实现起来却很复杂。所以本文就为大家整理了一下实现的示例代码,需要的可以参考一下
    2023-04-04
  • 原生javascript实现图片放大镜效果

    原生javascript实现图片放大镜效果

    这篇文章主要为大家详细介绍了原生javascript实现图片放大镜效果,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-01-01
  • JavaScript原生对象之String对象的属性和方法详解

    JavaScript原生对象之String对象的属性和方法详解

    这篇文章主要介绍了JavaScript原生对象之String对象的属性和方法详解,本文讲解了length、charAt()、charCodeAt()、concat()、indexOf()、lastIndexOf()等方法属性,需要的朋友可以参考下
    2015-03-03
  • 利用JS判断客户端类型你应该知道的四种方法

    利用JS判断客户端类型你应该知道的四种方法

    这篇文章主要给大家总结介绍了关于利用JS判断客户端类型的四种方法,比如通过通过判断浏览器的userAgent、检查是否是移动端(Mobile)、ipad、iphone、微信、QQ等的方法,需要的朋友可以参考借鉴,下面
    2017-12-12
  • JS实现页面跳转链接的几种方式汇总

    JS实现页面跳转链接的几种方式汇总

    这篇文章主要介绍了JS实现页面跳转链接的几种方式,简单总结了几种页面跳转功能的实现,有使用js跳转页面,返回上一次预览界面及button按钮添加事件跳转,本文结合实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2024-01-01

最新评论