Node.js and crypto library - node.js

I'm having weird issues with Node's crypto library. I wrote this simple AES testing script:
var cipher = crypto.createCipher('aes-256-cbc','InmbuvP6Z8')
var text = "123|123123123123123";
cipher.update(text,'utf8','hex')
var crypted = cipher.final('hex')
var decipher = crypto.createDecipher('aes-256-cbc','InmbuvP6Z8')
decipher.update(crypted,'hex','utf8')
var dec = decipher.final('utf8')
When I do console.log(dec), it's null. For some reason if I set test to "123|123123", it works. So why does "123|123123" work but "123|123123123123123" doesn't?

You need to store the return from cipher.update as well as cipher.final to be sure you have everything.
cipher.update "returns the enciphered contents, and can be called many times with new data as it is streamed":
http://nodejs.org/docs/v0.2.5/api.html#cipher-update-247
cipher.final "returns any remaining enciphered contents".
I think you just append the results with each call like this:
var crypto = require('crypto');
var cipher = crypto.createCipher('aes-256-cbc','InmbuvP6Z8');
var text = "123|123123123123123";
var crypted = cipher.update(text,'utf8','hex');
crypted += cipher.final('hex');
var decipher = crypto.createDecipher('aes-256-cbc','InmbuvP6Z8');
var dec = decipher.update(crypted,'hex','utf8');
dec += decipher.final('utf8');
I get '12443a347e8e5b46caba9f7afc93d71287fbf11169e8556c6bb9c51760d5c585' for crypted and '123|123123123123123' for dec in the above with node v0.2.5

RandomEtc is correct, but just in case anyone stumbling on this question is using 'base64' as their encoding: Don't. Stick to 'hex'. At least as of 0.4.2, there's a bug that can result in corrupted data when 'base64' is used. See: https://github.com/joyent/node/issues/738/

Please note that the += operator will not work in later versions of node.js. Please follow the advice given in Node.js Crypto class returning different results with updated version and use Buffer.concat()

Related

Make Nodejs encrypt and decrypt function up to date

I'm trying to make my small function up to date, it generate 2 warnings:
(node:8944) [DEP0106] DeprecationWarning: crypto.createDecipher is deprecated.
(node:8944) Warning: Use Cipheriv for counter mode of aes-256-ctr:
Code:
var crypto = require('crypto'),
algorithm = 'aes-256-ctr',
password = 'd6F3Efeq';
function encrypt(text){
var cipher = crypto.createCipher(algorithm,password)
var crypted = cipher.update(text,'utf8','hex')
crypted += cipher.final('hex');
return crypted;
}
function decrypt(text){
var decipher = crypto.createDecipher(algorithm,password)
var dec = decipher.update(text,'hex','utf8')
dec += decipher.final('utf8');
return dec;
}
This encrypt and decrypt wonderfully, but it generate some errors. I tried the new syntax, and I have a hard time figuring it out. If someone could provide an up to date demo, you're the best. Thank you
PS: I don't want to use createDecipherIv, I only want to use a key if this make sense
Install crypto-js:
npm i --save crypto-js
and use it:
const crypto = require('crypto-js'),
password = 'd6F3Efeq';
function encrypt(text){
const result = crypto.AES.encrypt(text, password);
return result.toString();
}
function decrypt(text){
const result = crypto.AES.decrypt(text, password);
return result.toString(crypto.enc.Utf8);
}
or You can use cryptr

NodeJS SHA1 get raw output (PHP SHA1 raw output equivalent)

In PHP, the code below returns the raw output of the SHA1 of the "string"
sha1("string", true);
What is the nodeJS equivalent of getting the SHA1 raw output?
Edit: I made some test and this line:
crypto.createHash('sha1').update('string').digest('base64');
generates same output as php's
base64_encode(sha1('string', true));
My issue occurs when I try to concatenate a string and the result of sha1, the get the sha1 again:
base64_encode(sha1(sha1("string", true) . "another string", true))
Different with nodejs:
var stringhash = crypto.createHash('sha1').update('string').digest();
crypto.createHash('sha1').update("another string" + stringhash).digest('base64')
Something like this:
const crypto = require('crypto');
let digest = crypto.createHash('sha1').update('string').digest();
process.stdout.write( digest );
EDIT: the equivalent of your second example:
let hash1 = crypto.createHash('sha1').update('string').digest();
let hash2 = crypto.createHash('sha1').update(hash1).update('another string');
let digest = hash2.digest('base64');

Crypto module is not working with latest node 7.10

The following code snippet is working in Node 0.12.18 (replace Buffer.from to new Buffer) but it's not working with the latest Node version (7.10.0)
Can anybody explain me why this is happening?? Anything is missing in below code.
/* Node.js */
var crypto = require('crypto');
var algorithm = 'aes-256-ctr';
var data = "Dhanet-Kalan-Chittorgarh"
var encryption_key = "VHUz1dxrhsowwEYGqUnPcE4wvAyz7Vmb";
var encryption_data = _encrypt()
console.log('data for encryption :: ' + data);
console.log('encrypted data :: ' + encryption_data);
console.log('decrypted data :: ' + _decrypt(encryption_data));
function _decrypt(_encryption_data){
var decipher, dec, chunks, itr_str;
// remove itr string
itr_str = _encryption_data.substring(_encryption_data.length-24);
_encryption_data = _encryption_data.substring(0, _encryption_data.length-24);
decipher = crypto.createDecipheriv(algorithm, encryption_key, Buffer.from(itr_str, "base64"));
chunks = []
chunks.push( decipher.update( Buffer.from(_encryption_data, "base64").toString("binary")) );
chunks.push( decipher.final('binary') );
dec = chunks.join("");
dec = Buffer.from(dec, "binary").toString("utf-8");
return dec;
}
function _encrypt(){
//random alpha-numeric string
var itr_str = Buffer.from(randomString(16)).toString('base64') ; // "3V5eo6XrkTtDFMz2QrF3og==";
var cipher = crypto.createCipheriv(algorithm, encryption_key, Buffer.from(itr_str, "base64"));
var chunks = [];
chunks.push(cipher.update( Buffer.from(data), 'utf8', 'base64'));
chunks.push(cipher.final('base64'));
var crypted = chunks.join('');
crypted = crypted.concat(itr_str);
return crypted;
}
function randomString(len, an)
{
an = an&&an.toLowerCase();
var str="", i=0, min=an=="a"?10:0, max=an=="n"?10:62;
for(;i++<len;){
var r = Math.random()*(max-min)+min <<0;
str += String.fromCharCode(r+=r>9?r<36?55:61:48);
}
return str;
}
Node.js v6 introduced some backward-incompatible changes to crypto which are causing this.
I've documented the exact reason in this answer, but because that question is related to hashing I'm reluctant to close your question as a duplicate.
The fix is similar, though (you need to pass binary as encoding for decipher.update(), otherwise it will default to utf-8):
chunks.push( decipher.update( Buffer.from(_encryption_data, "base64"), 'binary') );

Using SHA-256 with NodeJS Crypto

I'm trying to hash a variable in NodeJS like so:
var crypto = require('crypto');
var hash = crypto.createHash('sha256');
var code = 'bacon';
code = hash.update(code);
code = hash.digest(code);
console.log(code);
But looks like I have misunderstood the docs as the console.log doesn't log a hashed version of bacon but just some information about SlowBuffer.
What's the correct way to do this?
base64:
var crypto = require('crypto');
const hash = crypto.createHash('sha256').update(input).digest('base64');
hex:
var crypto = require('crypto')
const hash = crypto.createHash('sha256').update(input).digest('hex');
nodejs (8) ref
const crypto = require('crypto');
const hash = crypto.createHash('sha256');
hash.on('readable', () => {
const data = hash.read();
if (data) {
console.log(data.toString('hex'));
// Prints:
// 6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50
}
});
hash.write('some data to hash');
hash.end();
you can use, like this, in here create a reset token (resetToken), this token is used to create a hex version.in database, you can store hex version.
// Generate token
const resetToken = crypto.randomBytes(20).toString('hex');
// Hash token and set to resetPasswordToken field
this.resetPasswordToken = crypto
.createHash('sha256')
.update(resetToken)
.digest('hex');
console.log(resetToken )
Similar to the answers above, but this shows how to do multiple writes; for example if you read line-by-line from a file and then add each line to the hash computation as a separate operation.
In my example, I also trim newlines / skip empty lines (optional):
const {createHash} = require('crypto');
// lines: array of strings
function computeSHA256(lines) {
const hash = createHash('sha256');
for (let i = 0; i < lines.length; i++) {
const line = lines[i].trim(); // remove leading/trailing whitespace
if (line === '') continue; // skip empty lines
hash.write(line); // write a single line to the buffer
}
return hash.digest('base64'); // returns hash as string
}
I use this code ensure generated lines of a file aren't edited by someone manually. To do this, I write the lines out, append a line like sha256:<hash> with the sha265-sum, and then, upon next run, verify the hash of those lines matches said sha265-sum.

Node.js function to generate RSA keys using Open SSL

I'm using Node.js as a server side language and I would like to generate an RSA key pairs for any user that registers himself on my website. I'm using a module called keypair. It's working fine for keys with small sizes but when I generate keys with 2048 in size, it's taking so long to perform it so I would like to use Open SSL directly from Node.js using Node's child_process as described in the script down below :
var cp = require('child_process')
, assert = require('assert');
var privateKey, publicKey;
publicKey = '';
cp.exec('openssl genrsa 2048', function(err, stdout, stderr) {
assert.ok(!err);
privateKey = stdout;
console.log(privateKey);
makepub = cp.spawn('openssl', ['rsa', '-pubout']);
makepub.on('exit', function(code) {
assert.equal(code, 0);
console.log(publicKey);
});
makepub.stdout.on('data', function(data) {
publicKey += data;
});
makepub.stdout.setEncoding('ascii');
makepub.stdin.write(privateKey);
makepub.stdin.end();
});
This is working and more faster in key pairs generation than the Node.js keypair module so the issue I'm having is that I don't understand this code (if it's writing files on the server side and reading keys from them or not?) and I would like to turn this script into a function that returns a JSON or an array as result that holds the public and private key.
So any suggestion is welcome, thank you in advance.
Try this.. Moved the code around a little. Uses tmp file, which is deleted, possibly could be done without the tmp file, but this should work.
var cp = require('child_process')
, assert = require('assert')
, fs = require('fs')
;
// gen pub priv key pair
function genKeys(cb){
// gen private
cp.exec('openssl genrsa 2048', function(err, priv, stderr) {
// tmp file
var randomfn = './' + Math.random().toString(36).substring(7);
fs.writeFileSync(randomfn, priv);
// gen public
cp.exec('openssl rsa -in '+randomfn+' -pubout', function(err, pub, stderr) {
// delete tmp file
fs.unlinkSync(randomfn);
// callback
cb(JSON.stringify({public: pub, private: priv}, null, 4));
});
});
}
genKeys(console.log);
You can simply use the small rsa-json module
It's really easy to use and it's asynchronous:
var createRsaKeys = require('rsa-json');
createRsaKeys({bits: 1024}, function(err, keyPair) {
console.log(keyPair.private);
console.log(keyPair.public);
});
rsa-json does not make a direct uses of OpenSSL RSA_generate_key but uses ssh-keygen (from OpenSSH) which is a wrapper around OpenSSL. There is no direct security difference (see this for more information).
PS: Have a look at the only 48 lines of code composing rsa-json.
If you really want to use OpenSSL, you can have a look at the ursa module but:
It's not asynchronous
Is not maintained, the last commit was from Dec 21, 2012
The project is heavy, it does too much things like sugary stuff (base64 encoding, etc.).
It's have embedded C++ OpenSSL wrapper inside it, initialized during installation.
PS: keypair uses native JS, that's why it's very slow. It's not recommended with Node.js which is not good at performing CPU-intensive operations (but good with non-blocking events).

Resources