I need to get in Node js the same decrypted value that I get from my website in .NET C #
My code in the .NET C # class called Crypto is:
private static readonly string key = "Z8,omB0pxZwñ3h9s";
public string Encrypt(string data)
{
string encData = null;
byte[][] keys = GetHashKeys(key);
try
{
encData = EncryptStringToBytes_Aes(data, keys[0], keys[1]);
return encData;
}
catch (CryptographicException) {
return null;
}
catch (ArgumentNullException) {
return null;
}
}
public string Decrypt(string data)
{
string decData = null;
byte[][] keys = GetHashKeys(key);
try
{
decData = DecryptStringFromBytes_Aes(data, keys[0], keys[1]);
}
catch (CryptographicException) { }
catch (ArgumentNullException) { }
return decData;
}
private byte[][] GetHashKeys(string key)
{
byte[][] result = new byte[2][];
Encoding enc = Encoding.UTF8;
SHA256 sha2 = new SHA256CryptoServiceProvider();
byte[] rawKey = enc.GetBytes(key);
byte[] rawIV = enc.GetBytes(key);
byte[] hashKey = sha2.ComputeHash(rawKey);
byte[] hashIV = sha2.ComputeHash(rawIV);
Array.Resize(ref hashIV, 16);
result[0] = hashKey;
result[1] = hashIV;
return result;
}
//source: https://msdn.microsoft.com/de-de/library/system.security.cryptography.aes(v=vs.110).aspx
private static string EncryptStringToBytes_Aes(string plainText, byte[] Key, byte[] IV)
{
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
using (AesManaged aesAlg = new AesManaged())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt =
new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
return Convert.ToBase64String(encrypted);
}
//source: https://msdn.microsoft.com/de-de/library/system.security.cryptography.aes(v=vs.110).aspx
private static string DecryptStringFromBytes_Aes(string cipherTextString, byte[] Key, byte[] IV)
{
byte[] cipherText = Convert.FromBase64String(cipherTextString);
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("IV");
string plaintext = null;
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt =
new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
And what I have in Node js for now is this:
var sys = require ('sys'),
url = require('url'),
http = require('http'),
qs = require('querystring');
crypto = require('crypto-js');
var express = require('express');
var app = express();
var sql = require('mssql');
const getConn = require('./configVariables');
var config={
server : getConn.getServer(),
database : getConn.getDatabase(),
user : getConn.getUser(),
password : getConn.getPass(),
port:getConn.getPort(),
options: {
encrypt: false
}
};
http.createServer(function (req, res) {
try{
res.writeHead(200, {"Content-Type": "text/html;charset=UTF-8"});
var key = "Z8,omB0pxZwñ3h9s";
var secret = "ZZZZZZ";
e1 = crypto.AES.encrypt(secret, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
console.log("key: " + crypto.enc.Base64.stringify(e1.key));
console.log("iv: " + crypto.enc.Base64.stringify(e1.iv));
console.log("salt: " + crypto.enc.Base64.stringify(e1.salt));
console.log("ciphertext: " + crypto.enc.Base64.stringify(e1.ciphertext));
p = crypto.AES.decrypt(e1, key, {mode: crypto.mode.CBC, padding: crypto.pad.Pkcs7});
console.log("decrypted: " + crypto.enc.Utf8.stringify(p));
var isResponse = JSON.stringify({StatusCode:"200", info:"true", values:p})
res.end(isResponse);
}catch(err){
var errorResponse = JSON.stringify({StatusCode:"400", Descripcion:"ERROR: " + err})
res.end(errorResponse);
}
}).listen(process.env.PORT);
If I encrypt in .NET the variable ZZZZZZ gives me the result I need. But in Node js while the result may be a bit similar, it is not the same as I get in .NET and I really need to have the exact same result for both encryption and decryption.
Please I need help. I do not manage at all in what is encryption
The issue was not only because the IV was different. I provide more detail below:
In .NET C # the hashKey is a 32-byte array which comes from a 16-byte key string of text. But the hashIV is an array equivalent to the leading half of the array of the hashKey.
So in Node.js the algorithm to use is 'aes-256-cbc' assigning the keystring and IV variables the Buffer.from of bytes corresponding to each one, which must be the same as in C #.
Next I leave the Node.js solution that gave me the same result.
const crypto = require('crypto');
algorithm = "aes-256-cbc",
keystring = Buffer.from([ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32]),
iv = Buffer.from([ 1, 2, 3, 4, 5, ,6 ,7 ,8 9, 10, 11, 12, 13, 14, 15, 16]);
inputEncoding = 'utf8',
outputEncoding = 'base64';
function Encrypt(text) {
let cipher = crypto.createCipheriv(algorithm,keystring, iv);
let encrypted = cipher.update(text, inputEncoding, outputEncoding)
encrypted += cipher.final(outputEncoding);
return encrypted;
}
function Decrypt(encrypted) {
let decipher = crypto.createDecipheriv(algorithm,keystring, iv)
let dec = decipher.update(encrypted, outputEncoding, inputEncoding)
dec += decipher.final(inputEncoding);
return dec;
}
var enc = Encrypt("ZZZZZZ");
console.log("enc: " + enc);
var dec = Decrypt(enc);
console.log("dec: " + dec);
The bytes specified in the answer are not really what was captured in C #, but I leave them as a sample.
If it works for someone, great.