Crypto: Stream interface is not padded #5570

Closed
buschtoens opened this Issue May 27, 2013 · 11 comments

Projects

None yet

7 participants

@buschtoens

When using the stream interface for crypto.Cipher and crypto.Decipher .setAutoPadding(true) does not have any effect. This is understandable, as padding every read event would extremely bloat up the resulting code.

However, when the source stream closes, crypto fails with TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length, indicating, that the final block could not be encoded, as it does not meet the block length. When using auto padding, the (De-)Cipher object should automatically pad the last read event.

Sample code provoking the error:

var net = require("net")
  , crypto = require("crypto");

var credentials = { algorithm: "aes192", password: "password" }
  , decipher = crypto.createDecipher(credentials.algorithm, credentials.password)
  , cipher = crypto.createCipher(credentials.algorithm, credentials.password);

decipher.setAutoPadding(true);
cipher.setAutoPadding(true);

net.createServer(function(socket) {
  socket.pipe(socket);
}).listen(2000);

var socket = net.connect(2000);

socket.pipe(decipher).pipe(process.stdout);
process.stdin.pipe(cipher).pipe(socket); 

cipher.write("Too short.");
cipher.end();

StackOverflow

@buschtoens

Upon studying the source, I found out, that the interface is implemented correctly. However, I still get an error when ending the cipher.

@isaacs
Collaborator
isaacs commented Jun 5, 2013

Cygwin is not supported. Please use Windows directly, or msysgit bash.

@isaacs isaacs closed this Jun 5, 2013
@isaacs
Collaborator
isaacs commented Jun 5, 2013

Sorry, I can't read, apparently.

This was right next to a "Cygwin: ..." bug in the list, and my brain merged the two words.

@isaacs isaacs reopened this Jun 5, 2013
@ixe013
ixe013 commented Aug 2, 2013

You have set your pipes like this :

stdin | cipher | socket (loopback) | decipher | stdout

But you bypass the encryption by writing directly to the socket, using them like this :

socket (loopback) | decipher | stdout

Try with this code :

//cipher to the loopback socket, to decipher and stdout
cipher.pipe(socket).pipe(decipher).pipe(process.stdout);

//write some data 
cipher.write("Too short.");

I posted the full working code as an answer to your StackOverflow question about this issue.

@inscore
inscore commented Aug 16, 2013

When I attempt to AES256 cipher / decipher files with crypto I am seeing the same error as @silvinci, unlike his case I am not using sockets or pipes. Cipher / decipher plain text works fine.

@buschtoens

Sorry for not responding. Had some weird Gmail filters... I'll build a correct test case.

Sent from Mailbox for iPhone

On Fri, Aug 16, 2013 at 4:22 AM, Scot Inscore notifications@github.com
wrote:

When I attempt to AES256 cipher / decipher files with crypto I am seeing the same error as @silvinci, unlike his case I am not using sockets or pipes. Cipher / decipher plain text works fine.

Reply to this email directly or view it on GitHub:
#5570 (comment)

@paulshapiro

I'm encountering this very error.

It seems to happen only when trying to decipher short buffers.

Is it my code, perhaps?

Example buffer input: <Buffer 73 3a 35 34 34 30 32 3a 30>

function decrypt_buffer(buffer, password)
{
    var password_buffer = new Buffer(password);
    var decipher = crypto.createDecipher('aes-256-cbc', password_buffer);
    var decryptedBuffers = [decipher.update(buffer)];
    decryptedBuffers.push(decipher.final());
    var decrypted = Buffer.concat(decryptedBuffers);

    return decrypted;
}

Result is that decipher.final() throws:

TypeError: error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length
    at Decipher.Cipher.final (crypto.js:292:27)
@indutny
Member
indutny commented Apr 29, 2014

@paulshapiro could you please paste a complete code sample that reproduces the problem? (Note that it should not contain any non-core dependencies).

@ixe013
ixe013 commented Apr 29, 2014

My guess is that your input buffer is not encrypted. It reads s:54402:0.

As for your question, CBC mode requires padding. The only difference is that short buffers will fail on the first block. But then again, with 9 bytes you have two 64 bits blocks. The second block would be one byte of data and 7 bytes of padding, probably something like FF 07 07 07 07 07 07 07, with FF the encrypted byte.

@paulshapiro

@indutny I would definitely do so normally, but this is a particularly complex case as I'm not sure what part of my code was generating that particular input buffer.

@ixe013 you're totally right. It wasn't being encrypted ,and I figured out where, too. Thanks very much for pointing that out, and I appreciate the info about CBC mode.

@jasnell
Member
jasnell commented May 26, 2015

Unable to reproduce the error. Closing. Can reopen if necessary

@jasnell jasnell closed this May 26, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment