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")); 
    } 
}

相关文章

  • 详解webpack的文件监听实现(热更新)

    详解webpack的文件监听实现(热更新)

    这篇文章主要介绍了详解webpack的文件监听实现(热更新),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • 细说webpack源码之compile流程-rules参数处理技巧(2)

    细说webpack源码之compile流程-rules参数处理技巧(2)

    这篇文章主要介绍了webpack源码之compile流程-rules参数处理技巧的相关知识,需要的朋友参考下吧
    2017-12-12
  • Bootstrap轮播插件简单使用方法介绍

    Bootstrap轮播插件简单使用方法介绍

    这篇文章主要为大家详细介绍了Bootstrap轮播插件简单使用方法,介绍了使用bootstrap轮播插件的作用,感兴趣的小伙伴们可以参考一下
    2016-06-06
  • JavaScript实现构造json数组的方法分析

    JavaScript实现构造json数组的方法分析

    这篇文章主要介绍了JavaScript实现构造json数组的方法,结合实例形式对比分析了javascript构造json数组的实现方法及相关操作注意事项,需要的朋友可以参考下
    2018-08-08
  • Javascript操作表单实例讲解(下)

    Javascript操作表单实例讲解(下)

    这篇文章主要介绍了Javascript操作表单实例讲解(下)的相关资料,非常不错,具有参考借鉴价值,需要的朋友可以参考下
    2016-06-06
  • Bootstrap打造一个左侧折叠菜单的系统模板(一)

    Bootstrap打造一个左侧折叠菜单的系统模板(一)

    这篇文章主要介绍了Bootstrap打造一个左侧折叠菜单的系统模板(一)的相关资料,需要的朋友可以参考下
    2016-05-05
  • 三种动态加载js的jquery实例代码另附去除js方法

    三种动态加载js的jquery实例代码另附去除js方法

    这篇文章主要介绍了三种动态加载js的jquery实例代码另附去除js方法,需要的朋友可以参考下
    2014-04-04
  • JS实现横向轮播图(初级版)

    JS实现横向轮播图(初级版)

    这篇文章主要为大家详细介绍了JS实现横向轮播图的初级版,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-01-01
  • javascript中mouseenter与mouseover的异同

    javascript中mouseenter与mouseover的异同

    javascript中mouseover和mouseenter的区别主要在于监听对象的子元素是否触发事件。mouseover:鼠标移入监听对象中,或者从监听对象的一个子元素移入另一个子元素中时触发该事件。mouseenter:鼠标移入监听对象时触发,在监听对象内移动不会触发。
    2017-06-06
  • 微信小程序实现禁止分享代码实例

    微信小程序实现禁止分享代码实例

    这篇文章主要介绍了微信小程序实现禁止分享代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-10-10

最新评论