Behdad
Behdad

Reputation: 1629

Encrypting file in Node via Crypto and Stream

I want to read from a stream then encrypt it and finally write it to another file. This is my code:

var fs = require('fs');
var crypto = require('crypto');
var infile = fs.createReadStream('a.dmg');
var outfile = fs.createWriteStream('b.dmg');
var encrypt = crypto.createCipher('aes192', 'behdad');
var size = fs.statSync('a.dmg').size;
console.log(size);
infile.on('data',function(data) {
    var percentage = parseInt(infile.bytesRead) / parseInt(size);
    console.log(percentage * 100);
    var encrypted = encrypt.read(data);
    console.log(encrypted);
    if(encrypted){
        console.log(encrypted);
        outfile.write(encrypted);
    }


});
infile.on('close', function() {
    encrypt.end();
     outfile.close();

});

But it returns an empty file, and encrypted is null. What is the problem? I don't want to use pipe .

Upvotes: 0

Views: 2416

Answers (1)

Artjom B.
Artjom B.

Reputation: 61922

You really want to use Cipher#update and Cipher#final instead of Stream#read, because the function signature is read([size]) and data is not a size.

var fs = require('fs');
var crypto = require('crypto');
var infile = fs.createReadStream('a.dmg');
var outfile = fs.createWriteStream('b.dmg');
var encrypt = crypto.createCipher('aes192', 'behdad');
var size = fs.statSync('a.dmg').size;
console.log(size);
infile.on('data',function(data) {
    var percentage = parseInt(infile.bytesRead) / parseInt(size);
    console.log(percentage * 100);
    var encrypted = encrypt.update(data);
    console.log(encrypted);
    if(encrypted){
        console.log(encrypted);
        outfile.write(encrypted);
    }
});
infile.on('close', function() {
    outfile.write(encrypt.final());
    outfile.close();

});

Since crypto.createCipher is deprecated now. You should use crypto.createCipheriv where you provide a key and IV. That means that you should stretch the password that you use with PBKDF2 or similar to get a key and generate a random IV to get semantic security. Since the salt for PBKDF2 and the IV are not supposed to be secret, they can be written in front of the ciphertext. Since they have always the same length (salt is usually 8-16 bytes and IV always 16 bytes for AES-CBC), you know how many bytes you have to read in order to get those values back. Keep in mind that the decryption code has to have proper error handling.

Upvotes: 1

Related Questions