Search code examples
node.jscryptographynode-crypto

PKCS5 Padding with node.js crypto


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?


Solution

  • 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()
    ]);