Use openssl_decrypt() with passphase (not key/iv)

Multi tool use
Multi tool use
The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP


Use openssl_decrypt() with passphase (not key/iv)



I'm trying to decrypt some data that has been encrypted with a passphrase and aes-256-cbc method in a PHP script.


aes-256-cbc



Here is how I encrypt the original data


printf "Hello" | openssl enc -e -base64 -A -aes-256-cbc -k "MYPASSWORD"

// output
U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=



When I try to decrypt it in command-line it works fine


printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD"

// output
Hello



BUT when I use openssl_decrypt() in my PHP script it doesn't work!!


$result = openssl_decrypt("U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=", 'AES-256-CBC', "MYPASSWORD");
var_dump($result);

//output
bool(false)



I append the following lines to get the error


while ($msg = openssl_error_string())
echo $msg . "<br />n";



And it returns:



error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad
decrypt



I know that I should use a key/iv pair but I am not able to extract it from my passphrase with any salt. How can I get it to make the following command work?


printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -K ??????????????? -iv ????????????????

// expected output !!!
Hello



EDIT:



I tried to get key/iv with -P argument but it doesn't work


-P


printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD" -p
salt=9D5AE06E8A2B627C
key=8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF0A5FC65E67E2A8313FA
iv =4150125DCCD36F73A9F08F3020151A04
Hello

printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -K 8ACC4E30E9128FBB0763DDDA8998A7141DFDC77B9DADF05E67E2A8313FA -iv 4150125DCCD36F73A9F08F3020151A04
bad decrypt
140735954895816:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529:
??G?"r!C???&C&??




2 Answers
2



The issue here is that you are not using EVP_BytesToKey. This is the OpenSSL KDF used to derive a key and IV from your password.


EVP_BytesToKey



Note that it is insecure. You should prefer passing a hex key and IV directly to openssl enc.


openssl enc



There is a difference between the password (or passphrase) used as a parameter to openssl enc via the -k option (in your case "MYPASSWORD") and the key parameter that the PHP function openssl_decrypt() expects. The -k option to openssl enc is a passphrase of any length from which an actual 256 bits encryption key will be derived. That is also the key that the PHP openssl_decrypt() function needs. This encryption key is 256 bits because you have chosen aes-256.


openssl enc


-k


"MYPASSWORD"


key


openssl_decrypt()


-k


openssl enc


openssl_decrypt()


aes-256



You can get to know what that derived encryption key is by adding the -p option when invoking openssl enc. This also prints the iv, another parameter that you will need to use with the PHP openssl_decrypt() function. For example:


-p


openssl enc


iv


openssl_decrypt()


printf "Hello" | openssl enc -e -base64 -A -aes-256-cbc -k "MYPASSWORD" -nosalt -p
key=E0FAC2DD2C00FFE30F27A6D14568CB4F12EB84676A3A2BFB172A444C3BBB831F
iv =5A79774BB4B326EED949E6871FC27697
sp0z18QezUO8tSy7tgjOEw==



These printed key and iv values are the ones that you will need to feed into your PHP openssl_decrypt() function invocation, like this:


key


iv


openssl_decrypt()


$ciphertext = 'sp0z18QezUO8tSy7tgjOEw==';
$key = hex2bin('E0FAC2DD2C00FFE30F27A6D14568CB4F12EB84676A3A2BFB172A444C3BBB831F');
$iv = hex2bin('5A79774BB4B326EED949E6871FC27697');
$result = openssl_decrypt($ciphertext, 'AES-256-CBC', $key, 0, $iv);
var_dump($result);



Running the PHP script now results in success:


$ php decrypt.php
string(5) "Hello"



You may have noticed the extra -nosalt option when running openssl enc. Salt is used to add some randomness/uniqueness to the key derivation process and -nosalt omits that step. As a result, the key, iv and ciphertext will be the same in every run (if the same passphrase and plaintext are used) and you should be able to exactly reproduce the output. If you do not use -nosalt, your experiment will still work but the key, iv and ciphertext values will be different for each run.


-nosalt


openssl enc


-nosalt


key


iv


ciphertext


-nosalt


key


iv


ciphertext



Another option would be to let the PHP code derive the key and iv from the passphrase before invoking openssl_decrypt(). To do that, you will have to inspect the code of the enc tool for the openssl version that you are using. There you can see which key derivation function is used -- it depends on the version of openssl you are using as well as the options you are giving it -- and whether that is available in the PHP bindings of openssl.


key


iv


openssl_decrypt()


enc


openssl


openssl


openssl



Update, responding to your comment where you add the information that you only have the ciphertext and the passphrase available and that ciphertext was created with crypto-js.


crypto-js



Looking at the source code of crypto-js, it mentions in a comment in the source file evpkdf.js that "the key derivation function is meant to conform with EVP_BytesToKey", which is the same function that most openssl versions use. So you should be able to use the openssl enc tool to extract the key and the iv by using the -p option, like this:


crypto-js


evpkdf.js


openssl


openssl enc


key


iv


-p


$printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD" -p
salt=71A87BEBF4581AB3
key=917293FEC17514C078D156A8C4787B04A585167BD997E884E4C4219FEA0DC2A1
iv =DA6A91BC5F86B1EEE5C57DF97282C204



(which you have confirmed in another comment by now as well) and then use those when invoking the PHP function, as described above. Note that you will have to do this for every ciphertext separately, because the salt (and thus the key and iv) were chosen differently, randomly by crypto-js for each encryption action. To do this in PHP directly, see my previous remark: the required functionality does not seem to be available in its decrypt module.


salt


key


iv


crypto-js


decrypt



All that said, you would probably be better off moving away from the key derivation that openssl enc and crypto-js use and that relies on the proprietary mechanism implemented by the OpenSSL EVP_ByesToKey function. Even openssl enc now warns about this being deprecated .


openssl enc


crypto-js


EVP_ByesToKey


openssl enc



Instead, start using a standard algorithm like PBKDF2. This is supported by more recent versions of openssl enc and I have spotted it in the source code of the crypto-js and PHP crypto modules as well (but have never used those myself). If you have a database of encrypted data that you need to keep, you can re-encrypt its contents one time, using the old approach to decrypt and the PKDBF2 approach to encrypt.


openssl enc


crypto-js


crypto





Hi @Reinier. Thank you for you help! I understand your answer but my problem is that I have some ciphertexts and its passphrase. I used CryptoJS to generate ciphertexts and I stored them in DB. And now I need to retrieve the original string in a PHP script. So I need to get key/iv from the passphrase. I can't generate a new ciphertext. It should be possible because openssl in cmd-line is able to decrypt ciphertexts with only passphrase
– B 7
19 hours ago





What openssl cmd-line command do you use to decrypt those ciphertexts with only the passphrase?
– Reinier Torenbeek
18 hours ago




openssl





printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD"
– B 7
18 hours ago


printf "U2FsdGVkX1+dWuBuiitifH4zu1Yv/l7+HcfIqR/wxSc=" | openssl enc -d -base64 -A -aes-256-cbc -k "MYPASSWORD"





OK, just add the -p option to that line and it will print the key and the iv that you need to use in your PHP script. I added this to the answer.
– Reinier Torenbeek
18 hours ago


-p


key


iv


PHP





I added a final remark about a better way forward... In a nutshell: stop using proprietary openssl stuff.
– Reinier Torenbeek
16 hours ago






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

ysC Oi2I8rAB lKef,Pu e kMo,4
a,k,LjdoQSVAOxV6FSxW,sV16sPKaUMtf9D Pev3O6LsnI qyQkbtS3AlXjApDotrKg9 DuWRFy RvznqBKRzL7tIdXHeeeZEU

Popular posts from this blog

Visual Studio Code: How to configure includePath for better IntelliSense results

Spring cloud config client Could not locate PropertySource

Makefile test if variable is not empty