1

The docs for node.js crypto indicate that padding is inserted automatically into the input stream. I have a simple test program that needs to compute the SHA1 hash of a cleartext, then encrypt that 20-byte hash use AES-256/CBC with PKCS5 padding. Here is my test code:

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

var key = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
            0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
            0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
            0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f ];

var iv = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
           0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f ];

var test_string = "This is the string I am signing";

// Create SHA1 hash of our string
var sha1Hash = crypto.createHash("sha1");
sha1Hash.update(test_string, "utf8");
var sha1 = sha1Hash.digest();

var aesCipher =
        crypto.createCipheriv("aes-256-cbc", (new Buffer(key)), (new Buffer(iv)));
aesCipher.update(sha1, "binary");
var encrypted = aesCipher.final("binary");

fs.writeFile('data/node_encrypted.bin', encrypted, function (error) {
    if (error)
        throw error;
    console.log("File saved!");
});

However, this produces a file that is only 23 bytes in length. I expected that with proper PKCS5 padding, the output would be 32-bytes. What am I missing?

gevorg
  • 4,835
  • 4
  • 35
  • 52
Greg R
  • 133
  • 3
  • 8

1 Answers1

4

For one thing, you're discarding the first part of the encrypted contents by ignoring the return value of aesCipher.update(). Also, since your update() does not specify an output encoding, it's returning a Buffer, yet your final() is returning a 'binary' string. You might try instead:

var encrypted = Buffer.concat([
  aesCipher.update(sha1, "binary"),
  aesCipher.final()
]);
mscdex
  • 104,356
  • 15
  • 192
  • 153
  • Thank you. This was the problem. It wasn't clear to me that cipher.final() would not produce the entire encrypted contents. – Greg R May 28 '14 at 16:28
  • Thank you! This helped me solve a similar issue with decryption where I was seeing partially decrypted strings. Solved it with a similar approach: `return Buffer.concat([decipher.update(new Buffer(data, 'base64')),decipher.final()]).toString('utf8')` – Stano Aug 23 '17 at 20:34
  • I agree, @GregR - the Node docs don't seem very clear here: "The cipher.update() method can be called multiple times with new data until cipher.final() is called." My understanding here was that final() will accumulate all update() calls. – Stano Aug 23 '17 at 20:43