-----------------先贴代码--------------------------- 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(''));
----------------------------end-----------------------------
按照上面的方式,做加密是可以过的
但是当我加上别人的AES加密配置后(要解密他们的),就不行了 (他们用的是C#)
-----------------别人的配置数据------------------------
加密方式 AES 运算模式 ECB 块大小 128(位) 填充模式 零字节组成的字符串 密钥向量 { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF } 密钥 89622015104709087435617163207900 编码 UTF8 密文传输编码 BASE64 样例 明文:123456 密文:0cfAwa9X9XRpr53SKjfiug== (改数据配置,我用C#代码校验过,是可以通过的,与样例匹配)
按照该配置处理,会出现以下三个问题 Key='89622015104709087435617163207900’ IV=[0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF] 1、TypeError: Not a buffer at TypeError (native) at new Cipheriv (crypto.js:187:16) at Object.Cipheriv (crypto.js:185:12) at Object.exports.AESEncrypt (d:\Node Work\MemberConduct\Tools\AES_KeChuan.js:23:23) at d:\Node Work\MemberConduct\routes\index.js:20:23 at Layer.handle [as handle_request] (d:\Node Work\MemberConduct\node_modules\express\lib\router\layer.js:95:5) at next (d:\Node Work\MemberConduct\node_modules\express\lib\router\route.js:131:13) at Route.dispatch (d:\Node Work\MemberConduct\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (d:\Node Work\MemberConduct\node_modules\express\lib\router\layer.js:95:5) at d:\Node Work\MemberConduct\node_modules\express\lib\router\index.js:277:22
当我将IV转成buffer后,会出现以下问题 2、 Invalid IV length Error: Invalid IV length at Error (native) at new Cipheriv (crypto.js:187:16) at Object.Cipheriv (crypto.js:185:12) at Object.exports.AESEncrypt (d:\Node Work\MemberConduct\Tools\AES_KeChuan.js:23:23) at d:\Node Work\MemberConduct\routes\index.js:20:23 at Layer.handle [as handle_request] (d:\Node Work\MemberConduct\node_modules\express\lib\router\layer.js:95:5) at next (d:\Node Work\MemberConduct\node_modules\express\lib\router\route.js:131:13) at Route.dispatch (d:\Node Work\MemberConduct\node_modules\express\lib\router\route.js:112:3) at Layer.handle [as handle_request] (d:\Node Work\MemberConduct\node_modules\express\lib\router\layer.js:95:5) at d:\Node Work\MemberConduct\node_modules\express\lib\router\index.js:277:22
尝试按照例子代码中的IV=’’,会出现第三个问题 3、Invalid key length
npm 上搜索过好几个aes库,但是与数据配置都不符合, 有用Node做过这方面的,麻烦指点一下,不甚感激
/**
- aes加密
- @param data
- @param secretKey
- @param secretIV */ exports.aesEncrypt = function(data, secretKey, iv) { try{ var cipherEncoding = ‘base64’;//有可能是base64 var clearEncoding = ‘utf8’; var cipher = crypto.createCipheriv(‘aes-128-cbc’,secretKey, iv); return cipher.update(data,clearEncoding,cipherEncoding) + cipher.final(cipherEncoding); }catch(e){ logger.error('aesEncrypt error: ’ + err); return ‘’; }
}
/**
- aes解密
- @param data
- @param secretKey
- @param secretIV
- @returns {*} */ exports.aesDecrypt = function(data, secretKey, iv) { try{ var cipherEncoding = ‘base64’;//有可能是base64 var clearEncoding = ‘utf8’; var cipher = crypto.createDecipheriv(‘aes-128-cbc’,secretKey, iv); return cipher.update(data,cipherEncoding,clearEncoding) + cipher.final(clearEncoding); }catch(err){ logger.error('aseDecrypt error: ’ + err); return ‘’; } }
这个是我用的,和php的aes能对上,已经在用
AES算法,key的长度必须是128位,也就是16 byte,buffer的长度必须为16,因为这是AES的一个数据块长度。 AES在CBC/PKCS5Padding模式下,使用的向量长度也是16 byte。 问题2和问题3都是长度不匹配的问题
另外,ECB模式下是没有加密向量的,只有CBC模式才有加密向量。C#的数据给的貌似是ECB
还有一个需要注意的是,每个平台秘钥生成策略可能不一样,同一个string生成的buffer可能不同。保险的方法是确保秘钥buffer是相同的
@TakWolf 确实这样的 现在的问题就是C#加密出来的确实可以,但Node就是无法实现, 按照上面的配置数据,得使用 aes-256-cbc模式才可以,但是加密出来的内容与样例不一致 -------------------------贴C#代码------------------------------------ public class AESEncryption { private static byte[] _key1 = { 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF }; const string key = “89622015104709087435617163207900”; //加密 public static string AESEncrypt(string plainText) { if (!string.IsNullOrEmpty(plainText)) { SymmetricAlgorithm des = Rijndael.Create(); byte[] inputByteArray = Encoding.UTF8.GetBytes(plainText); des.Key = Encoding.UTF8.GetBytes(key); des.IV = _key1; des.BlockSize = 128; des.Padding = PaddingMode.Zeros; des.Mode = CipherMode.ECB; using (MemoryStream ms = new MemoryStream()) { using (CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write)) { cs.Write(inputByteArray, 0, inputByteArray.Length); cs.FlushFinalBlock(); } byte[] cipherBytes = ms.ToArray(); return Convert.ToBase64String(cipherBytes); } } else return string.Empty; } //解密 public static string AESDecrypt(string cipherText) { if (!string.IsNullOrEmpty(cipherText)) { byte[] buffer = Convert.FromBase64String(cipherText);
SymmetricAlgorithm des = Rijndael.Create();
des.Key = Encoding.UTF8.GetBytes(key);
des.IV = _key1;
des.BlockSize = 128;
des.Padding = PaddingMode.Zeros;
des.Mode = CipherMode.ECB;
byte[] decryptBytes = new byte[cipherText.Length];
using (MemoryStream ms = new MemoryStream(buffer))
{
using (CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read))
{
cs.Read(decryptBytes, 0, decryptBytes.Length);
}
return Encoding.UTF8.GetString(decryptBytes).TrimEnd('\0');
}
}
else return string.Empty;
}
}