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

例子一:

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

(0)

相关推荐

  • php rsa加密解密使用详解

    1.加密解密的第一步是生成公钥.私钥对,私钥加密的内容能通过公钥解密(反过来亦可以) 下载开源RSA密钥生成工具openssl(通常Linux系统都自带该程序),解压缩至独立的文件夹,进入其中的bin目录,执行以下命令: 复制代码 代码如下: openssl genrsa -out rsa_private_key.pem 1024 openssl pkcs8 -topk8 -inform PEM -in rsa_private_key.pem -outform PEM -nocrypt -out

  • 2个比较经典的PHP加密解密函数分享

    项目中有时我们需要使用PHP将特定的信息进行加密,也就是通过加密算法生成一个加密字符串,这个加密后的字符串可以通过解密算法进行解密,便于程序对解密后的信息进行处理. 最常见的应用在用户登录以及一些API数据交换的场景. 笔者收录了一些比较经典的PHP加密解密函数代码,分享给大家.加密解密原理一般都是通过一定的加密解密算法,将密钥加入到算法中,最终得到加密解密结果. 1.非常给力的authcode加密函数,Discuz!经典代码(带详解): 复制代码 代码如下: function authcode

  • PHP实现加密的几种方式介绍

    PHP中的加密方式有如下几种 1. MD5加密 string md5 ( string $str [, bool $raw_output = false ] ) 参数 str  --  原始字符串. raw_output  --  如果可选的 raw_output 被设置为 TRUE,那么 MD5 报文摘要将以16字节长度的原始二进制格式返回. 这是一种不可逆加密,执行如下的代码 $password = '123456'; echo md5($password); 得到结果是e10adc3949

  • php中AES加密解密的例子小结

    aesDemo.php: 例子, 复制代码 代码如下: <?phprequire_once('./AES.php');//$aes = new AES();$aes = new AES(true);// 把加密后的字符串按十六进制进行存储//$aes = new AES(true,true);// 带有调试信息且加密字符串按十六进制存储$key = "this is a 32 byte key";// 密钥$keys = $aes->makeKey($key);$encod

  • 两种JavaScript的AES加密方式(可与Java相互加解密)

    由于JavaScript属于弱类型脚本语言,因此当其与强类型的后台语言进行数据交互时会产生各种问题,特别是加解密的操作.本人由于工作中遇到用js与Java进行相互加解密的问题,在网上查了很多资料及代码段,均无法解决.后总结多篇文档内容终于找到解决办法,现记录与此: 下面给大家介绍两种JavaScript的AES加密方式,具体详情如下所示: 第一种:加解密时需要秘钥(key)和秘钥偏移量(iv)的情况,在线验证地址:http://www.seacha.com/tools/aes.html //该方

  • 原生js的RSA和AES加密解密算法

    本文实例为大家分享了js中RSA和AES加密解密详细代码,供大家参考,具体内容如下 <!doctype html> <html> <head> <meta charset='UTF-8'> </head> <body> <div class='test'></div> <script type="text/javascript"> function encrypt(data, k

  • 兼容PHP和Java的des加密解密代码分享

    php代码: <?php class DES { var $key; var $iv; //偏移量 function DES($key, $iv=0) { $this->key = $key; if($iv == 0) { $this->iv = $key; } else { $this->iv = $iv; } } //加密 function encrypt($str) { $size = mcrypt_get_block_size ( MCRYPT_DES, MCRYPT_MO

  • PHP可逆加密/解密函数分享

    函数源码 复制代码 代码如下: function encrypt($data, $key) { $prep_code = serialize($data); $block = mcrypt_get_block_size('des', 'ecb'); if (($pad = $block - (strlen($prep_code) % $block)) < $block) { $prep_code .= str_repeat(chr($pad), $pad); } $encrypt = mcryp

  • 详解nodejs与javascript中的aes加密

    一.简介 1.aes加密简单来说,在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标准用来替代原先的DES,已经被多方分析且广为全世界所使用.高级加密标准已然成为对称密钥加密中最流行的算法之一. 2.AES的区块长度固定为128 比特,密钥长度则可以是128,192或256比特:而Rijndael使用的密钥和区块长度可以是32位的整数倍,以128位为下限,256比特为上限.包括AES-ECB,AES-CBC,AES-CTR,AES-OFB,AES-CFB. 3.在

  • JS实现AES加密并与PHP互通的方法分析

    本文实例讲述了JS实现AES加密并与PHP互通的方法.分享给大家供大家参考,具体如下: 有关数据加密解密问题,有很多钟加密方式: 这里我讲述下js和php实现AES互通 js加密: 首先引入这几个js文件 本站下载地址. <script type="text/JavaScript" src="/CryptoJS/aes.js"></script> <script type="text/javascript" src=

  • Java与Node.js利用AES加密解密出相同结果的方法示例

    前言 工作中遇到nodejs端通过aes加密,安卓客户端Java解密,同样nodejs也需要解密安卓客户端加密过来的内容,发现两个加密结果不一样,查询资料发现java端需要对密钥再MD5加密一遍,以下是Java与Node.js利用AES加密解密出相同结果的方法,需要的朋友们下面来一起学习学习吧. JAVA代码如下: package g.g; import java.security.MessageDigest; import javax.crypto.Cipher; import javax.c

  • PHP 加密解密内部算法

    将它们打包成一个文件就叫fun.php吧 复制代码 代码如下: <?php function passport_encrypt($txt, $key) { srand((double)microtime() * 1000000); $encrypt_key = md5(rand(0, 32000)); $ctr = 0; $tmp = ''; for($i = 0;$i < strlen($txt); $i++) { $ctr = $ctr == strlen($encrypt_key) ?

随机推荐