compute hmac from message bytes and key bytes in javascript - javascript

I'm trying to reproduce the following code in javascript
var hashInput = "a::string::to::hash";
var privateKey = "C0B615950F9D577A4EAF64C9B4F2E50F3DA2C6BB6F790FA346E9732788B29A08AC5444F1B82984DB190A75D3861CC4802D598EBF0025FD1C327928F43EB1C80E";
byte[] inputBytes = Encoding.UTF8.GetBytes(hashInput);
byte[] keyBytes = Encoding.UTF8.GetBytes(privateKey);
HMACSHA256 hmac = new HMACSHA256(keyBytes);
hmac.Initialize();
var clientHash = hmac.ComputeHash(inputBytes);
var base64 = Convert.ToBase64String(clientHash);
But i ignore how can i import Enocde and HMACSHA256. I found the code in the following answer:
stackoverflow answer
This is what i've tried so far
const HashMAC = (key, message) => {
let keyBytes = Buffer.from(key, 'base64');
let messageBytes = Buffer.from(message, 'utf8');
// i don't know which library should i use, in crypto js thay're talking about
message and key noy bytes i tried but nothing.
const base64 = Buffer.from(hmac, 'base64');
return base64;
};

Related

I need to replicate this from Java to JavaScript (NodeJs)

I try to get the same functionality of java class to replicate in NodeJs, but I can't do it. I don't understand all the JavaCode, specialy when the instance sing() (what's return). for that can't replicate into NodeJs
Java Code
public String generateSignature(String key, String stringToSign) throws Exception {
Signature signatureInstance = Signature.getInstance("SHA256WithRSA");
ServiceKeyRep keyRep = new ServiceKeyRep(KeyRep.Type.PRIVATE, "RSA", "PKCS#8", Base64.getDecoder().decode(key));
PrivateKey resolvedPrivateKey = (PrivateKey) keyRep.readResolve();
signatureInstance.initSign(resolvedPrivateKey);
byte[] bytesToSign = stringToSign.getBytes("UTF-8");
signatureInstance.update(bytesToSign);
String signatureString = Base64.getEncoder().encodeToString(signatureBytes);
return signatureString;
}
And I try this on Node JS
const privateKey = fs.readFileSync('myKey.pem', 'utf-8');
const stringToSign = new Int8Array([ myData ]);
const data = Buffer.from(stringToSign);
const sign = crypto.sign("RSA-SHA256", data , privateKey);
const signature = sign.toString('base64');
//Printing the signature
console.log(`Signature:\n\n ${signature}`);
but when I print, the out is not the same
Using crypto library we can do something similar in JS. Adapt as appropriate, this is just a reference.
const fs = require('fs');
const crypto = require('crypto');
function generateSignature(key, stringToSign) {
const privateKey = fs.readFileSync(key, 'utf-8');
const sign = crypto.createSign('RSA-SHA256');
sign.update(stringToSign);
const signature = sign.sign(privateKey, 'base64');
return signature;
}
const key = 'myKey.pem';
const stringToSign = 'myData';
const signature = generateSignature(key, stringToSign);
console.log(`Signature:\n\n${signature}`);

How to use Node JS to decrypt a file that was encrypted using C#

I have files encrypted in C# (using DES, PKCS7). I need to decode these files in Node JS.
The code I use to decrypt in C# looks like this:
public string SSFile_Reader( string fileToDecrypt )
{
DESCryptoServiceProvider provider = new DESCryptoServiceProvider
{
Key = Encoding.UTF8.GetBytes( "13^07v90" ),
IV = Encoding.UTF8.GetBytes( "13^07v90" ),
Padding = PaddingMode.PKCS7
};
using( FileStream streamToDecrypt = new FileStream( fileToDecrypt, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) )
{
ICryptoTransform cryptoTransform = provider.CreateDecryptor();
string outputString = "";
using( CryptoStream stream2 = new CryptoStream( streamToDecrypt, cryptoTransform, CryptoStreamMode.Read ) )
{
try
{
using( StreamReader reader = new StreamReader( stream2 ) )
{
try
{
outputString = reader.ReadToEnd();
}
catch
{
//handle error here
}
stream2.Close();
streamToDecrypt.Close();
return outputString;
}
}
catch( Exception exception )
{
//handle error here
}
}
}
return '';
}
I literally need to convert the above to Node JS. I have tried the Node JS code below, but the output is just some random stuff rather than the original encrypted string:
const { Readable } = require("stream");
const { scrypt, scryptSync, randomFill, createCipheriv, createDecipheriv } = require('crypto');
const fs = require('fs');
const [, , pathToEncryptedFile] = process.argv;
if (!pathToEncryptedFile) {
console.log('No file to decrypt')
exit()
}
const keyAndIv = '31335e3037763930'; //hex equivalence of 13^07v90
const key = Buffer.from(keyAndIv, 'hex');
const iv = Buffer.from(keyAndIv, 'hex');
const decryptedData = '';
const decipher = createDecipheriv('des', key, iv);
const readableStream = Readable.from(fs.createReadStream(pathToEncryptedFile)
.pipe(decipher));
readableStream.on("data", (chunk) => {
decryptedData += chunk.toString()
})
readableStream.on('end', function () {
console.log({decryptedData})
});
readableStream.on('error', function (err) {
console.log({err})
});
I also tried using crypto-js to no avail (https://github.com/brix/crypto-js/issues/396).
This is an example of one of the files I need to decrypt: https://files.fm/u/6pewftkk2
I can also give the C# code that does the encryption if the C# code given above for the decryption does not suffice
One possible variant is to load the ciphertext completely from the file system and decrypt it:
var crypto = require('crypto')
var fs = require('fs')
const algorithm = 'des'; // defaults to 'des-cbc';
const password = 'Password used to generate key';
const key = '13^07v90';
const iv = '13^07v90';
const ciphertext = fs.readFileSync('<path to high_classes.ssdata>');
const decipher = crypto.createDecipheriv(algorithm, key, iv);
const plaintext = decipher.update(ciphertext, '', 'utf8') + decipher.final();
console.log(plaintext);
which outputs the following plaintext (for the linked file):
SSS1
SSS2
SSS3
Alternatively, especially for large data, the plaintext can also be streamed to a file. To do this, replace the last block with:
const decipher = crypto.createDecipheriv(algorithm, key, iv);
const readStream = fs.createReadStream('<path to high_classes.ssdata>');
const writeStream = fs.createWriteStream('<path to file where decrypted data should be saved>');
readStream.pipe(decipher).pipe(writeStream);
which creates a file containing the decrypted data.
Note that DES is outdated and insecure these days. Using the key as an IV is also insecure. Typically, a random IV is generated during encryption and passed to the other side along with the ciphertext (usually concatenated).

Sign hex digest message with js crypto library

I need your help. I have C# example how to sign message digest
signatureFormatter.SetHashAlgorithm("SHA1");
string keyText = Convert.ToBase64String(_certificate.PrivateKey);
byte[] signature = signatureFormatter.CreateSignature(hash);
return signature;
Later it converts it to base64:
Convert.ToBase64String(signature)
I need to achieve same result with node builtin library crypto, what I wrote:
const crypto = require('crypto');
...
const sig = crypto.createSign('RSA-SHA1');
sig.update(hashValue, 'hex');
sig.end();
const signature = sig.sign(privateKeyString, 'base64');
As result I'm getting different signatures for same hash, please help me, how to solve this problem
*** Update ***
Original C# function
private byte[] CreateSignature(byte[] hash)
{
RSAPKCS1SignatureFormatter signatureFormatter = new RSAPKCS1SignatureFormatter(_certificate.PrivateKey);
signatureFormatter.SetHashAlgorithm("SHA1");
byte[] signature = signatureFormatter.CreateSignature(hash);
return signature;
}
Update node.js function
const hashValue= '332a400fdab5b01efcd8407c61987495270ec1b6';
const sig = crypto.createSign('RSA-SHA1');
sig.update(Buffer.from(hashValue, 'utf-8'));
sig.end();
const sign = sig.sign(privateKeyString, 'base64');

AES encryption method in NodeJS similar to C sharp function

I have a function written in C#. Basically the function is used to generate a token on the basis of parameters like text and key.
public string Encrypt(string input, string key) {
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toEncrptArray = UTF8Encoding.UTF8.GetBytes(input);
Aes kgen = Aes.Create("AES");
kgen.Mode = CipherMode.ECB;
kgen.Key = keyArray;
ICryptoTransform cTransform = kgen.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncrptArray, 0, toEncrptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
I'm trying to search any same alternative for the above function in NodeJS or run this function inside the NodeJS script through any compiler.
I have tried the crypto-js module in NodeJS but got a different token string. Please suggest the alternative function or any idea about running this function inside the NodeJS script.
My Recent code in NodeJS :
First Method :
var CryptoJS = require("crypto-js");
// Encrypt
var ciphertext = CryptoJS.AES.encrypt("<input>", "<key>").toString();
Second Method :
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
password = '<key>';
function encrypt(text){
var cipher = crypto.createCipher(algorithm,password)
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
return crypted;
}
Both the method is giving different token if compared to C# function.
The AES algorithm used in the C# code is AES 128-bit in ECB mode.
We can perform the same encryption in Node.js (and decrypt as well if we wish), using the following code:
Node.js Code
const crypto = require("crypto");
function encrypt(plainText, key, outputEncoding = "base64") {
const cipher = crypto.createCipheriv("aes-128-ecb", key, null);
let encrypted = cipher.update(plainText, 'utf8', outputEncoding)
encrypted += cipher.final(outputEncoding);
return encrypted;
}
function decrypt(cipherText, key, outputEncoding = "utf8") {
const cipher = crypto.createDecipheriv("aes-128-ecb", key, null);
let encrypted = cipher.update(cipherText)
encrypted += cipher.final(outputEncoding);
return encrypted;
}
const KEY = Buffer.from("abcdefghijklmnop", "utf8");
console.log("Key length (bits):", KEY.length * 8);
const encrypted = encrypt("hello world", KEY, "base64");
console.log("Encrypted string (base64):", encrypted);
// And if we wish to decrypt as well:
const decrypted = decrypt(Buffer.from(encrypted, "base64"), KEY, "utf8")
console.log("Decrypted string:", decrypted);
C# Code
using System;
using System.Text;
using System.Security.Cryptography;
public class Program
{
public static void Main()
{
Console.WriteLine("Result: " + Encrypt("hello world", "abcdefghijklmnop"));
}
public static string Encrypt(string input, string key) {
byte[] keyArray = UTF8Encoding.UTF8.GetBytes(key);
byte[] toEncrptArray = UTF8Encoding.UTF8.GetBytes(input);
Aes kgen = Aes.Create("AES");
kgen.Mode = CipherMode.ECB;
kgen.Key = keyArray;
ICryptoTransform cTransform = kgen.CreateEncryptor();
byte[] resultArray = cTransform.TransformFinalBlock(toEncrptArray, 0, toEncrptArray.Length);
return Convert.ToBase64String(resultArray, 0, resultArray.Length);
}
}
The results for the encryption (with plaintext and key as above) are:
.Net: f7sSBDV0N6MOpRJLpSJL0w==
Node.js: f7sSBDV0N6MOpRJLpSJL0w==
Obviously we must not use this key in production!

Encrypt / decrypt file (CryptoJS)

When working on the task "Encrypt / decrypt file (CryptoJS.AES)" I encountered a problem:
the official documentation is not described the process of encrypting and decrypting files.
The problem was that after decryption the file was corrupted. This was due to improper decoding of the decrypt files.
After decryption it is necessary to execute the code:
decryptFile.toString(CryptoJS.enc.Utf8);
I want to share with you my decision:
import CryptoJS from 'crypto-js';
import fs from "fs";
const key = 'SECRET_KEY',
iv = '9De0DgMTCDFGNokdEEial'; // You must dynamically create
const encrypt = (filePath)=> {
const dataFile = fs.readFileSync(filePath),
dataBase64 = dataFile.toString('base64'),
encryptFile = CryptoJS.AES.encrypt(dataBase64, key, {iv: iv}),
buffer = new Buffer(encryptFile.toString(), 'base64');
fs.writeFileSync(filePath, buffer);
}
const decrypt = (filePath, fileType)=> {
const dataFile = fs.readFileSync(filePath);
const decryptFile = CryptoJS.AES.decrypt(dataFile.toString('base64'),
key, {iv: iv});
// Return data: URL
return 'data:' + fileType + ';base64,' +
decryptFile.toString(CryptoJS.enc.Utf8);
// Or save decrypt file
// const result = decryptFile.toString(CryptoJS.enc.Utf8);
// const buffer = new Buffer(result, 'base64');
// fs.writeFileSync(filePath, buffer);
}

Categories

Resources