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