use*_*114 5 node.js rc2-cipher
我使用Key和IV使用RSC2-cbc算法在C#中使用现有的加密和解密登录.现在我将在node.js中实现相同的功能.所以我写了以下代码来加密和解密.我面临的问题是node.js加密字符串(chiper)或解密字符串与C#encryptrd字符串不匹配.
现有的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());
Run Code Online (Sandbox Code Playgroud)
等效/翻译的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#.
Run Code Online (Sandbox Code Playgroud)
虽然您使用的算法不同...这是我在 C# 中的参考实现...我已经对节点实现应该是什么进行了评论...并且它匹配...
我当时的目标是保持 .Net 端与节点端的默认设置兼容......
有关的:
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
* /sf/ask/1295166281/
* /sf/ask/858307831/
* /sf/ask/560577741/
*/
/* 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();
}
}
}
}
}
}
}Run Code Online (Sandbox Code Playgroud)
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;
}Run Code Online (Sandbox Code Playgroud)
我的 .Net 代码引用了HashUtility,这并不是严格需要的,而且我没有可用 scrypt 的完整 node.js 实现...它主要用于测试。
| 归档时间: |
|
| 查看次数: |
1100 次 |
| 最近记录: |