17

I have the following encrypted data:

U2FsdGVkX1+21O5RB08bavFTq7Yq/gChmXrO3f00tvJaT55A5pPvqw0zFVnHSW1o

The pass to decrypt it is: password

(it's the example from gibberish-aes)

In the command line using openssl:

echo "U2FsdGVkX1+21O5RB08bavFTq7Yq/gChmXrO3f00tvJaT55A5pPvqw0zFVnHSW1o" | openssl enc -d -aes-256-cbc -a -k password

The output is:

Made with Gibberish\n

With my NodeJS application:

  var decipher = crypto.createDecipher('aes-256-cbc', "password");
  var dec = decipher.update("U2FsdGVkX1+21O5RB08bavFTq7Yq/gChmXrO3f00tvJaT55A5pPvqw0zFVnHSW1o",
     'base64', 'utf8');
  dec += decipher.final('utf8');

I have the following error TypeError: DecipherFinal fail at the decipher.final line.

Am I missing something ? Thanks.

o_nix
  • 1,146
  • 1
  • 16
  • 30
Sandro Munda
  • 39,921
  • 24
  • 98
  • 123
  • 1
    Great question. I found that openssl uses a salt every time, so you need a `-nosalt` switch. With no salt it uses same IV and derived key every time, you can see them providing a `-p` switch. Then you can do `createDecipheriv(data, key, iv)` in the node. But it does not decode the text properly anyway. So I'm stuck too. – o_nix Sep 08 '12 at 21:51
  • @owlstead I've used **key** and **iv** directly, does this use **PBKDF2**? http://pastebin.com/uhxTRn9T here are my code and results. What is wrong? – o_nix Sep 10 '12 at 22:39
  • I've looked in the code and it should use the openssl key derivation without a salt. I'm not sure about the IV. I do know that with Java I cannot decrypt the openssl result either. Plot thickens. – Maarten Bodewes Sep 11 '12 at 20:57
  • Here are some similar questions and answers: [Decrypting AES256 with node.js returns wrong final block length](https://stackoverflow.com/q/21292142/608639), [Nodejs decrypt using crypto error wrong final block length](https://stackoverflow.com/q/23111388/608639), [Getting error wrong final block length while decrypting AES256](https://stackoverflow.com/q/32038267/608639), [Decrypt file in Node.js encrypted using OpenSSL](https://stackoverflow.com/q/44482151/608639), [How to decipher string in node.js which is encrypted in crypto.js](https://stackoverflow.com/q/28359128/608639). – jww Jun 11 '17 at 10:19

1 Answers1

17

The encrypted data starts with a 8 byte "magic" indicating that there is a salt (the ASCII encoding of "Salted__"). Then the next 8 bytes is the salt. Now the bad news: Node.js does not seem to use the salt for the EVP_BytesToKey method:

int key_len = EVP_BytesToKey(cipher, EVP_md5(), NULL,
  (unsigned char*) key_buf, key_buf_len, 1, key, iv);

That NULL is the salt.

This has been verified using a Java test application (using the right salt) - the result string was returned.

Please leave out the salt using the OpenSSL -nosalt switch and try again.

[EXAMPLE]

OpenSSL CLI:

openssl enc -aes-256-cbc -nosalt -a -k password
owlstead
Mh5yxIyZH+fSMTkSgkLa5w==

NodeJS crypto:

var crypto=require('crypto')
var cipher=crypto.createDecipher('aes-256-cbc', "password")
var enc = cipher.update("Mh5yxIyZH+fSMTkSgkLa5w==", 'base64', 'utf8')
enc += cipher.final('utf8')

[LATE EDIT] Note that using secret key derivation with a salt and large work factor may be paramount to security. You'd better use a very unique, high entropy password otherwise your encrypted data may be at risk.


[REALLY LATE EDIT] OpenSSL 1.1.0c changed the digest algorithm used in some internal components. Formerly, MD5 was used, and 1.1.0 switched to SHA256. Be careful the change is not affecting you in both EVP_BytesToKey and commands like openssl enc.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • encrypted data after Base64 decoding, obviously. – Maarten Bodewes Sep 11 '12 at 22:11
  • But I use `-nosalt` as I said before... I know about `Salted__` magic signature in default OpenSSL encoding results. My pastebin example contains `-nosalt`. – o_nix Sep 11 '12 at 22:19
  • That `U2FsdGVkX1+21O5RB08bavFTq7Yq/gChmXrO3f00tvJaT55A5pPvqw0zFVnHSW1o` string does however contain the salt. You can easily see that it is too large otherwise (even if you don't simply decode the base64 and view the ASCII encoded first 8 bytes). – Maarten Bodewes Sep 11 '12 at 22:24
  • Ouch, it really works with `createDecipher()` and `-nosalt`! I haven't tried that combination, only `…iv()` version. You are my and @Sandro Munda hero! :) – o_nix Sep 11 '12 at 22:55
  • 2
    How do you encrypt using node crypto with the -nosalt option? – Ari Porad Feb 16 '13 at 02:33
  • 1
    i don't understand... you can't use "-nosalt" if you don't have control over the encryption. what if you need to decrypt files already encrypted with a salt? – Michael Jun 30 '16 at 23:08
  • You'd have to create your own `EVP_BytesToKey` derivation method in NodeJS, in all probability. Not that hard or risky compared to many other schemes, but still rather specialized work. – Maarten Bodewes Oct 14 '16 at 22:08