Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Invalid key length" when generating a cipher from binary encoded string #6696

Closed
dhritzkiv opened this issue May 11, 2016 · 4 comments
Closed
Labels
crypto Issues and PRs related to the crypto subsystem.

Comments

@dhritzkiv
Copy link
Contributor

dhritzkiv commented May 11, 2016

  • version: v.6.1.0
  • platforms:
    • 15.4.0 Darwin Kernel Version 15.4.0: Fri Feb 26 22:08:05 PST 2016; root:xnu-3248.40.184~3/RELEASE_X86_64 x86_64
    • Linux 3.13.0-29-generic # 53-Ubuntu SMP Wed Jun 4 21:00:20 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
  • module affected: crypto

Basic failing example:

const iv = crypto.randomBytes(16);
const salt = "foobar";
const hash = crypto.createHash("sha1");
hash.update(salt);

let key = hash.digest("binary");
key = key.substring(0, 16);

key.length // 16

const cipher = crypto.createCipheriv('aes-128-cbc', key, iv); //uncaughtException: Invalid key length 

Passing in a binary encoded string with a length of 16 causes the last line to throw. Adding more or removing bytes has no effect.

Passing a utf8 encoded line with a length of 16 doesn't throw.

This behaviour showed up with Node v6 (v5 worked fine).

@addaleax addaleax added the crypto Issues and PRs related to the crypto subsystem. label May 11, 2016
@mscdex
Copy link
Contributor

mscdex commented May 11, 2016

The default string encoding used by the crypto module changed in v6.0.0 from binary to utf8. So your binary string is being interpreted as utf8 and is most likely becoming larger than 16 bytes during that conversion process (rather than smaller than 16 bytes) due to invalid utf8 character bytes being added.

@dhritzkiv
Copy link
Contributor Author

Interesting. Based on your information, I was able to work around this by creating a Buffer from the binary-encoded string:

const iv = crypto.randomBytes(16);
const salt = "foobar";
const hash = crypto.createHash("sha1");

hash.update(salt);

let key = Buffer.from(hash.digest("binary").substring(0, 16), "binary");//buffer from binary string.

const cipher = crypto.createCipheriv('aes-128-cbc', key, iv); //works

Is this the recommended method of what I'm trying to do? Or am I over-complicating it?

@mscdex
Copy link
Contributor

mscdex commented May 11, 2016

Yes, you want to use a Buffer, but you don't need to deal with binary strings at all here, just do this:

const iv = crypto.randomBytes(16);
const salt = "foobar";
const hash = crypto.createHash("sha1");

hash.update(salt);

// `hash.digest()` returns a Buffer by default when no encoding is given
let key = hash.digest().slice(0, 16);

const cipher = crypto.createCipheriv('aes-128-cbc', key, iv);

@dhritzkiv
Copy link
Contributor Author

Ah! Much simpler. Thank you so much for your help.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
crypto Issues and PRs related to the crypto subsystem.
Projects
None yet
Development

No branches or pull requests

3 participants