2

I'm trying to perform AES CBC encryption with zero padding of a url query string. I'm using NodeJS's core crypto module. It's for use with http://www.blackoutrugby.com/game/help.documentation.php#category=35

I have a key and IV. When testing the following function I'm not getting the string returned in full. I believe this has to do with padding but am unsure how to apply it correct.

If it is the padding, can anyone show me how I should apply it? If not where am I going wrong? Also is cipher.final() of significance in this usercase?

Update: I've now included cipher.final() and things work fine with binary format but base64 gives me the truncated result. https://github.com/denishoctor/BlackoutRugbyNode/blob/master/crypto2.js is my full example code. Below is the crypto function:

function cryptoTest(data, key, iv, format) {
   var cipher = crypto.createCipheriv('aes-128-cbc', key, iv);
   var cipherChunks = [];
   cipherChunks.push(cipher.update(data, 'utf8', format));
   cipherChunks.push(cipher.final());

   var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
   var plainChunks = [];
   for (var i = 0;i < cipherChunks.length;i++) {
        plainChunks.push(decipher.update(cipherChunks[i], format, 'utf8'));
   }
   plainChunks.push(decipher.final());

   return {
       "encrypted": cipherChunks.join(''),
       "decrypted": plainChunks.join('')
   };
}

Thanks,
Denis

Denis Hoctor
  • 2,597
  • 4
  • 33
  • 51

2 Answers2

5

You are not putting the ciphertext returned by cipher.final into the decipher. Here's a simplified example. You need to collect the return values from every call to cipher.update as well as cipher.final and make sure each of those objects gets put into decipher.update.

UPDATE: here's a version that works fine with binary or hex as the encoding for the cipher text, but fails with base64. I have no idea why this is, but if you are OK with hex that should work fine.

UPDATE 2: Looks like base64 is a bug in node itself. See this answer to a similar question.

    var crypto = require('crypto');

    var data = "I am the clear text data";
    console.log('Original cleartext: ' + data);
    var algorithm = 'aes-128-cbc';
    var key = 'mysecretkey';
    var clearEncoding = 'utf8';
    var cipherEncoding = 'hex';
    //If the next line is uncommented, the final cleartext is wrong.
    //cipherEncoding = 'base64';
    var cipher = crypto.createCipher(algorithm, key);
    var cipherChunks = [];
    cipherChunks.push(cipher.update(data, clearEncoding, cipherEncoding));
    cipherChunks.push(cipher.final(cipherEncoding));
    console.log(cipherEncoding + ' ciphertext: ' + cipherChunks.join(''));
    var decipher = crypto.createDecipher(algorithm, key);
    var plainChunks = [];
    for (var i = 0;i < cipherChunks.length;i++) {
      plainChunks.push(decipher.update(cipherChunks[i], cipherEncoding, clearEncoding));

    }
    plainChunks.push(decipher.final(clearEncoding));
    console.log("UTF8 plaintext deciphered: " + plainChunks.join(''));
Community
  • 1
  • 1
Peter Lyons
  • 142,938
  • 30
  • 279
  • 274
  • Thanks for that. It's a big help. However when I add base64 encoding I get a truncated result! And idea why? > – Denis Hoctor May 24 '11 at 04:02
  • Your original source code has a mix of output_encoding base64 and binary. That's my guess. Let me try my example with consistent base64. – Peter Lyons May 24 '11 at 04:18
  • I've now updated the question and have a full example @ https://github.com/denishoctor/BlackoutRugbyNode/blob/master/crypto2.js – Denis Hoctor May 24 '11 at 04:35
  • Thanks Peter, afraid the API I'm working against requires base64 output :( – Denis Hoctor May 24 '11 at 06:09
  • 1
    Well, just encrypt to hex and then convert the hex to base64 outside of the node crypto library. Should be straightforward to do with a node library, third party library, or even forking a subprocess as a last resort. – Peter Lyons May 24 '11 at 06:38
  • 1
    ...or...just go fix the node bug. :-p – Peter Lyons May 24 '11 at 06:41
0

Standard crypto package only supports PKCS#7 padding. You have to disable automatic padding of standard crypto package of Node.js then you can write code to pad.

You can use padding algorithm from following package

https://github.com/tugrul/cryptian

tugrul
  • 136
  • 6