Node.js中AES加密和其它語(yǔ)言不一致問(wèn)題解決辦法
例子一:
這幾天被一個(gè)問(wèn)題困擾著。Nodejs的AES加密和Java,C#加密出來(lái)的不一致。當(dāng)然,這樣就不能解密了。糾結(jié)了許久:后來(lái)還是實(shí)在不行了,看了下源代碼,要不然還得繼續(xù)糾結(jié)下去。網(wǎng)上說(shuō),通常的nodejs AES和其他語(yǔ)言實(shí)現(xiàn)不一樣。好吧~~或許吧。
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(''));
的確,沒(méi)錯(cuò)~~加密解密成功。但是和java,C#中加密出來(lái)的不一樣啊。神啊。我想,大家都在這里糾結(jié)著吧~~對(duì)不對(duì)。其實(shí)只要加個(gè)向量,就可以和一致了。網(wǎng)上搜索出來(lái)的資源太少。才讓自己糾結(jié)那么久。好吧,正確代碼是:
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(''));
對(duì)比發(fā)現(xiàn),加密出來(lái)是一致的。好吧,結(jié)貼~~~我恨你,浪費(fèi)了我一天時(shí)間。
例子二:
工作中遇到nodejs端通過(guò)aes加密,安卓客戶端java解密,同意nodejs也需要解密安卓客戶端加密過(guò)來(lái)的內(nèi)容,發(fā)現(xiàn)兩個(gè)加密結(jié)果不一樣,查詢資料發(fā)現(xiàn)java端需要對(duì)密鑰za再M(fèi)D5加密一遍,以下是aes ecb加密的內(nèi)容,如果是cbc也同樣需要對(duì)秘鑰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);
}
/**
* 字符串轉(zhuǎn)字節(jié)數(shù)組
* @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;
}
/**
* 字節(jié)轉(zhuǎn)16進(jìn)制數(shù)組
* @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"));
}
}
- node.js之基礎(chǔ)加密算法模塊crypto詳解
- 淺談如何通過(guò)node.js對(duì)數(shù)據(jù)進(jìn)行MD5加密
- 淺析Node.js非對(duì)稱加密方法
- 使用node.js對(duì)音視頻文件加密的實(shí)例代碼
- node.JS md5加密中文與php結(jié)果不一致的解決方法
- Java與Node.js利用AES加密解密出相同結(jié)果的方法示例
- Node.js 數(shù)據(jù)加密傳輸淺析
- Node.js DES加密的簡(jiǎn)單實(shí)現(xiàn)
- NODE.JS加密模塊CRYPTO常用方法介紹
- node.JS的crypto加密模塊使用方法詳解(MD5,AES,Hmac,Diffie-Hellman加密)
相關(guān)文章
詳解webpack的文件監(jiān)聽(tīng)實(shí)現(xiàn)(熱更新)
這篇文章主要介紹了詳解webpack的文件監(jiān)聽(tīng)實(shí)現(xiàn)(熱更新),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09細(xì)說(shuō)webpack源碼之compile流程-rules參數(shù)處理技巧(2)
這篇文章主要介紹了webpack源碼之compile流程-rules參數(shù)處理技巧的相關(guān)知識(shí),需要的朋友參考下吧2017-12-12JavaScript實(shí)現(xiàn)構(gòu)造json數(shù)組的方法分析
這篇文章主要介紹了JavaScript實(shí)現(xiàn)構(gòu)造json數(shù)組的方法,結(jié)合實(shí)例形式對(duì)比分析了javascript構(gòu)造json數(shù)組的實(shí)現(xiàn)方法及相關(guān)操作注意事項(xiàng),需要的朋友可以參考下2018-08-08Bootstrap打造一個(gè)左側(cè)折疊菜單的系統(tǒng)模板(一)
這篇文章主要介紹了Bootstrap打造一個(gè)左側(cè)折疊菜單的系統(tǒng)模板(一)的相關(guān)資料,需要的朋友可以參考下2016-05-05三種動(dòng)態(tài)加載js的jquery實(shí)例代碼另附去除js方法
這篇文章主要介紹了三種動(dòng)態(tài)加載js的jquery實(shí)例代碼另附去除js方法,需要的朋友可以參考下2014-04-04javascript中mouseenter與mouseover的異同
javascript中mouseover和mouseenter的區(qū)別主要在于監(jiān)聽(tīng)對(duì)象的子元素是否觸發(fā)事件。mouseover:鼠標(biāo)移入監(jiān)聽(tīng)對(duì)象中,或者從監(jiān)聽(tīng)對(duì)象的一個(gè)子元素移入另一個(gè)子元素中時(shí)觸發(fā)該事件。mouseenter:鼠標(biāo)移入監(jiān)聽(tīng)對(duì)象時(shí)觸發(fā),在監(jiān)聽(tīng)對(duì)象內(nèi)移動(dòng)不會(huì)觸發(fā)。2017-06-06微信小程序?qū)崿F(xiàn)禁止分享代碼實(shí)例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)禁止分享代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-10-10