1

We have a legacy PHP system that encrypted some data via openssl_encrypt. The PHP code is pretty straight forward. (All values are randomly generated for this example, but are the same format and lengths as the real values and reproduce the same errors).

$in = '12345';
$method = 'AES-256-CBC';
$key = '5fjfwc7kp84z5yet358t';
$options = 0;
$iv = '8x69nt6qnptg3x4j';
openssl_encrypt($in, $method, $key, $options, $iv);

Decrypting via PHP is also pretty straight forward.

$in = 'yy03+cUpsq5uGWclBLtwIA==';
$method = 'AES-256-CBC';
$key = '5fjfwc7kp84z5yet358t';
$options = 0;
$iv = '8x69nt6qnptg3x4j';
openssl_decrypt($in, $method, $key, $options, $iv);

However, when trying to port it over to Node crypto I keep getting errors on key length, iv length, and numerous other errors as I try different approaches.

const input = Buffer.from('yy03+cUpsq5uGWclBLtwIA==');
const iv = Buffer.from('8x69nt6qnptg3x4j');
const key = Buffer.from('5fjfwc7kp84z5yet358t');

let decipher = crypto.createDecipheriv('aes-256-cbc', key, iv, 0);
let clearText = decipher.update(input, 'base64', 'utf8');
clearText += decipher.final('utf8');

I've probably tried half a dozen or more examples in NodeJS and all produce errors and fail to decrypt entirely.

Current error is "Invalid key length" which remains the error even if I restrict it to 16 characters.

12
  • The key size for AES-256 is 23 bytes. PHP can tolerate smaller keys (I think it pads with zero bytes), but Node will throw an exception. Also you don't decode your ciphertext. Commented Sep 27, 2018 at 15:18
  • crypto.stackexchange.com/questions/3298/… (no it doesn't pad with zeroes, and its an openssl thing, not a PHP thing) Commented Sep 27, 2018 at 15:19
  • @symcbean I was referring to key padding, not plaintext padding. But you're right, it is an openssl thing, it has nothing to do with the language. Commented Sep 27, 2018 at 15:30
  • I have tried padding the key to 23 bytes and it still gives a key length error. Also, what do you meany by "You don't decode your ciphertext"? Commented Sep 27, 2018 at 16:15
  • @Soabirw Sorry, that's a typo, I meant 32 bytes (256 bits = 32 bytes). And don't forget to base64-decode before decryption. Commented Sep 27, 2018 at 16:23

1 Answer 1

1

Padding and base64 processing was the solution. Working code looks closer to this:

const keyStr = '5fjfwc7kp84z5yet358t';
const diff = Math.abs(keyStr.length - 32);
const padding = Buffer.alloc(diff, 0x00);
const input = Buffer.from('yy03+cUpsq5uGWclBLtwIA==', 'base64');
const iv = Buffer.from('8x69nt6qnptg3x4j');
let key = Buffer.from('5fjfwc7kp84z5yet358t');
key = Buffer.concat([key, padding]);

const decipher = crypto.createDecipheriv('aes-256-cbc', key, iv, 0);
let clearText = decipher.update(input, 'base64', 'utf8');
clearText += decipher.final('utf8');
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.