Node.JS RC2-CBCencryption和解密密码与C#不匹配

我有一个现有的encryption和解密login在C#中使用RSC2-cbcalgorithm使用Key和IV。 现在我要在node.js中实现相同的function 所以我写了下面的代码来encryption和解密。 我面临的问题是node.jsencryption的string(chiper)或解密的string与C#encryptrdstring不匹配。

现有的C#代码

byte[] arrbIV = Encoding.ASCII.GetBytes("dleftaba"); byte[] arrbKey = Encoding.ASCII.GetBytes(Key); byte[] arrbData = Encoding.ASCII.GetBytes(sData); //Text to be encryptrd RC2 oEncryptor = new RC2CryptoServiceProvider(); oEncryptor.Mode = CipherMode.CBC; oEncryptor.Key = arrbKey; oEncryptor.IV = arrbIV; // Create memory stream to store encrypted string MemoryStream oMemoryStream = new MemoryStream(); CryptoStream oCryptoStream = new CryptoStream(oMemoryStream, oEncryptor.CreateEncryptor(), CryptoStreamMode.Write); // Peform the encryption oCryptoStream.Write(arrbData, 0, arrbData.Length); // We have written all the data in the stream and now we can apply padding oCryptoStream.Close(); string sRetVal = Convert.ToBase64String(oMemoryStream.ToArray()); 

等效/翻译的node.js代码

 var crypto = require('crypto') var SECRET_KEY = "435353553" var IV = "dleftaba" var ENCODING = 'base64' var text = "My Text" Encryption var cipher = crypto.createCipheriv('rc2-cbc',key, iv) var cryptedPassword = cipher.update(text, 'utf-8', 'base64') cryptedPassword+= cipher.final('base64') Decryption var decipher = crypto.createDecipheriv('rc2-cbc', SECRET_KEY, IV) var decryptedPassword = decipher.update(cryptedPassword, 'base64','utf-8') decryptedPassword += decipher.final('utf-8') Please suggest what is going wrong over here. Why node. js is not resulting into the identical chiper like C#. 

       

网上收集的解决方案 "Node.JS RC2-CBCencryption和解密密码与C#不匹配"

虽然不是你使用的algorithm相同…这里是我在C#中的参考实现 …我已经把节点的实现应该是什么意见…并匹配…

我当时的目标是保持.Net端与节点端的默认值兼容。

有关:

  • 在NodeJS和C#(.Net)中AES256encryption/解密
  • 在.NET中解密来自node.js的AES256encryption数据 – 如何从密码中获得IV和Key
  • C#版本的OpenSSL EVP_BytesToKey方法?
 using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Security.Cryptography; using System.Text; using System.Threading.Tasks; namespace T1.CoreUtils { public static class CryptoUtility { /* Wanting to stay compatible with NodeJS * https://stackoverflow.com/questions/18502375/aes256-encryption-decryption-in-both-nodejs-and-c-sharp-net/ * https://stackoverflow.com/questions/12261540/decrypting-aes256-encrypted-data-in-net-from-node-js-how-to-obtain-iv-and-key * https://stackoverflow.com/questions/8008253/c-sharp-version-of-openssl-evp-bytestokey-method */ /* EncrypteDefault - as NodeJS * var cipher = crypto.createCipher('aes-256-cbc', 'passphrase'); * var encrypted = cipher.update("test", 'utf8', 'base64') + cipher.final('base64'); */ public static string EncryptDefault(string input, string passphrase = null) { byte[] key, iv; PassphraseToDefaultKeyAndIV(RawBytesFromString(passphrase), null, 1, out key, out iv); return Convert.ToBase64String(EncryptBytes(Encoding.UTF8.GetBytes(input), key, iv)); } /* DecryptDefault - as NodeJS * var decipher = crypto.createDecipher('aes-256-cbc', 'passphrase'); * var plain = decipher.update(encrypted, 'base64', 'utf8') + decipher.final('utf8'); */ public static string DecryptDefault(string inputBase64, string passphrase = null) { byte[] key, iv; PassphraseToDefaultKeyAndIV(RawBytesFromString(passphrase), null, 1, out key, out iv); return Encoding.UTF8.GetString(DecryptBytes(Convert.FromBase64String(inputBase64), key, iv)); } public static string Encrypt(string input, string passphrase = null) { byte[] key, iv; PassphraseToSCryptKeyAndIV(passphrase, out key, out iv); return Convert.ToBase64String(EncryptBytes(Encoding.UTF8.GetBytes(input), key, iv)); } public static string Decrypt(string inputBase64, string passphrase = null) { byte[] key, iv; PassphraseToSCryptKeyAndIV(passphrase, out key, out iv); return Encoding.UTF8.GetString(DecryptBytes(Convert.FromBase64String(inputBase64), key, iv)); } static byte[] RawBytesFromString(string input) { var ret = new List<Byte>(); foreach (char x in input) { var c = (byte)((ulong)x & 0xFF); ret.Add(c); } return ret.ToArray(); } public static void PassphraseToSCryptKeyAndIV(string passphrase, out byte[] key, out byte[] iv) { var hashList = HashUtility.HashSCrypt(Encoding.UTF8.GetBytes(passphrase)).ToList(); key = new byte[32]; iv = new byte[16]; hashList.CopyTo(0, key, 0, 32); hashList.CopyTo(32, iv, 0, 16); } public static void PassphraseToDefaultKeyAndIV(byte[] data, byte[] salt, int count, out byte[] key, out byte[] iv) { List<byte> hashList = new List<byte>(); byte[] currentHash = new byte[0]; int preHashLength = data.Length + ((salt != null) ? salt.Length : 0); byte[] preHash = new byte[preHashLength]; System.Buffer.BlockCopy(data, 0, preHash, 0, data.Length); if (salt != null) System.Buffer.BlockCopy(salt, 0, preHash, data.Length, salt.Length); MD5 hash = MD5.Create(); currentHash = hash.ComputeHash(preHash); for (int i = 1; i < count; i++) { currentHash = hash.ComputeHash(currentHash); } hashList.AddRange(currentHash); while (hashList.Count < 48) // for 32-byte key and 16-byte iv { preHashLength = currentHash.Length + data.Length + ((salt != null) ? salt.Length : 0); preHash = new byte[preHashLength]; System.Buffer.BlockCopy(currentHash, 0, preHash, 0, currentHash.Length); System.Buffer.BlockCopy(data, 0, preHash, currentHash.Length, data.Length); if (salt != null) System.Buffer.BlockCopy(salt, 0, preHash, currentHash.Length + data.Length, salt.Length); currentHash = hash.ComputeHash(preHash); for (int i = 1; i < count; i++) { currentHash = hash.ComputeHash(currentHash); } hashList.AddRange(currentHash); } hash.Clear(); key = new byte[32]; iv = new byte[16]; hashList.CopyTo(0, key, 0, 32); hashList.CopyTo(32, iv, 0, 16); } public static byte[] EncryptBytes(byte[] input, byte[] Key, byte[] IV) { // Check arguments. if (input == null || input.Length <= 0) return new byte[0]; //nothing to encode if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key"); if (IV == null || IV.Length <= 0) throw new ArgumentNullException("Key"); // Create an RijndaelManaged object // with the specified key and IV. using (RijndaelManaged cipher = new RijndaelManaged()) { cipher.Key = Key; cipher.IV = IV; cipher.Mode = CipherMode.CBC; cipher.Padding = PaddingMode.PKCS7; // Create a decrytor to perform the stream transform. ICryptoTransform encryptor = cipher.CreateEncryptor(cipher.Key, cipher.IV); // Create the streams used for encryption. using (MemoryStream outputStream = new MemoryStream()) { using (CryptoStream encryptStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write)) { encryptStream.Write(input, 0, input.Length); encryptStream.FlushFinalBlock(); outputStream.Seek(0, 0); return outputStream.ToArray(); } } } } public static byte[] DecryptBytes(byte[] cipherText, byte[] Key, byte[] IV) { // Check arguments. if (cipherText == null || cipherText.Length <= 0) throw new ArgumentNullException("cipherText"); if (Key == null || Key.Length <= 0) throw new ArgumentNullException("Key"); if (IV == null || IV.Length <= 0) throw new ArgumentNullException("Key"); // Create an RijndaelManaged object // with the specified key and IV. using (var cipher = new RijndaelManaged()) { cipher.Key = Key; cipher.IV = IV; cipher.Mode = CipherMode.CBC; cipher.Padding = PaddingMode.PKCS7; // Create a decrytor to perform the stream transform. ICryptoTransform decryptor = cipher.CreateDecryptor(cipher.Key, cipher.IV); // Create the streams used for decryption. using (var inputStream = new MemoryStream(cipherText)) { using (var outputStream = new MemoryStream()) { using (CryptoStream decryptedStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read)) { var buffer = new byte[1024]; decryptedStream.Flush(); var read = decryptedStream.Read(buffer, 0, buffer.Length); while (read > 0) { outputStream.Write(buffer, 0, read); decryptedStream.Flush(); read = decryptedStream.Read(buffer, 0, buffer.Length); } outputStream.Seek(0, 0); return outputStream.ToArray(); } } } } } } } 

Node.js的

 var crypto = require('crypto'); module.exports = { encrypt: encryptValue, decrypt: decryptValue } function encryptValue(input, passphrase) { var cipher = crypto.createCipher('aes-256-cbc', passphrase); var encrypted = cipher.update(input, 'utf8', 'base64') + cipher.final('base64'); return encrypted; } function decryptValue(inputBase64, passphrase) { var decipher = crypto.createDecipher('aes-256-cbc', passphrase); var plain = decipher.update(inputBase64, 'base64', 'utf8') + decipher.final('utf8'); return plain; } 

我的.Net代码引用HashUtility这是不是严格需要,我没有我完整的node.js实现与scrypt可用…这主要是针对testing。