1

I am creating a Node.js application that can encrypt and decrypt image files. However when my code is run I get varying results: Sometimes the decrypted image looks like the original at the top but the bottom half looks corrupted, sometimes the decrypted image is completely there but looks like it was heavily compressed and sometimes the decrypted image is too corrupt to open. Here is an image that demonstrates this. The only thing these results have in common is the encrypted and decrypted images are double the file size of the original image.

const fs = require('fs');
const crypto = require('crypto');

var path = 'C:\\Users\\' + windowsUserName + '\\Desktop\\image';
    var fileExtension = '.jpg';
    var password = '1234';
    var algorithm = 'aes-256-cbc';

    var image = fs.createReadStream(path + fileExtension);

    var encryptedImage = fs.createWriteStream(path + ' encrypted' + fileExtension);
    var decryptedImage = fs.createWriteStream(path + ' decrypted' + fileExtension);

    var encrypt = crypto.createCipher(algorithm, password);
    var decrypt = crypto.createDecipher(algorithm, password);

    image.pipe(encrypt).pipe(encryptedImage);
    image.pipe(encrypt).pipe(decrypt).pipe(decryptedImage);

How do I fix the image corruption and file size doubling?

8
  • AES-CBC should be used with createCipherIv not createCipher. Commented Sep 13, 2018 at 4:48
  • I don't really understand how initialization vector's work so if you could tell me more that would be great! The answer I selected seems to work so could you explain to me why I should implement them? Commented Sep 13, 2018 at 5:14
  • Because without them your encryption is insecure and doesn't really work. Look up ECB mode on Wikipedia and look at the penguin. Commented Sep 13, 2018 at 5:16
  • The part I really don't get is this line: "it is important that an initialization vector is never reused under the same key". If I were to change my current code to use createCipherIv instead of createCipher wouldn't I be reusing the IV all the time? Commented Sep 13, 2018 at 5:20
  • Yes, that's why you should always generate a new random IV every time you encrypt. Getting encryption right is difficult, it's very delicate. The code you have, with respect, is pretty mediocre. Commented Sep 13, 2018 at 5:34

1 Answer 1

1

You are trying to decrypt the cypher before it is finished. If you wait until the pipe is done and read the encrypted file, it should not be garbled:

const fs = require('fs');
const crypto = require('crypto');

var path = 'file path';
    var fileExtension = '.jpg';
    var password = '1234';
    var algorithm = 'aes-256-cbc';

    var image = fs.createReadStream(path + fileExtension);
    var encryptedImage = fs.createWriteStream(path + ' encrypted' + fileExtension);
    var encrypt = crypto.createCipher(algorithm, password);
    image.pipe(encrypt).pipe(encryptedImage);

    encryptedImage.on("finish", function(){
        var decrypt = crypto.createDecipher(algorithm, password);
        var decryptedImage = fs.createWriteStream(path + ' decrypted' + fileExtension);
        var encryptedImage = fs.createReadStream(path + ' encrypted' + fileExtension);
        encryptedImage.pipe(decrypt).pipe(decryptedImage);
    })
Sign up to request clarification or add additional context in comments.

1 Comment

I thought I had ruled out that possibility in one of my tests but apparently I did it wrong, thanks.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.