1

I'm encrypting a JSON object using OpenSSL on the command line. However, when I send it using cURL and then try to decrypt it, I just get unprintable bytes. Here is my process:

Encrypting in OpenSSL

openssl aes-128-cbc -in object.json -out cipher.txt -pass pass:key.file -base64

cat object.json
{"payload":"this is a test"}

cat key.file
KWA6HNqb9UydXPbh72Vej82rT7NMVQZE

cat cipher.txt U2FsdGVkX1/OOX/XSRXXOCmxfak5TXbagG6ZSW6U95U+VLADuaH83zmP8hee017J

key.file is exactly 32 bytes. I have the same key.file residing on the server. I have verified that it is also 32 bytes.

Sending using cURL

curl --data "@cipher.txt" http://www.example.com/myscript.php

php script

$key = file_get_contents("key.file");
echo $key . "\n";

// get the ciphertext from the POST parameter   
$ciphertext = rawurlencode(file_get_contents("php://input"));
echo $ciphertext . "\n";

echo base64_decode(mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $ciphertext, MCRYPT_MODE_CBC));

And here is what I get back:

KWA6HNqb9UydXPbh72Vej82rT7NMVQZE U2FsdGVkX1%2FOOX%2FXSRXXOCmxfak5TXbagG6ZSW6U95U%2BVLADuaH83zmP8hee017J
���G�/

I don't see what I am doing wrong. Can anyone please show me where I am making my mistake? Thanks!

EDIT I also tried to use this command to decrypt, but I just get an empty string as a result:

echo base64_decode(openssl_decrypt($ciphertext, "AES-128-CBC", $key, OPENSSL_RAW_DATA));
AndroidDev
  • 20,466
  • 42
  • 148
  • 239
  • Have you tried using [openssl_decrypt](http://php.net/manual/en/function.openssl-decrypt.php) instead? – Jon Jan 10 '16 at 19:21
  • Yes. I just get an empty string for the decryption result. I'll edit my post to show that. Good suggestion. Thanks! – AndroidDev Jan 10 '16 at 19:34
  • Hmm. Another thought, have you tried base64 encoding the data after it's encrypted so it gets passed to the script without any possible errors? Judging from the `cat` result of it, that may be a possible issue. – Jon Jan 10 '16 at 19:42

1 Answers1

3

-pass pass:key.file means that you encrypt your plaintext with a key that is derived from the password key.file. If you want to use the first line of key.file, then you need to use -pass file:key.file. You probably don't want that, because passwords are not keys. PHP's mcrypt or openssl extensions don't provide a direct way to use the same key derivation from a password. You can use my code here to derive the same key and IV from the password.

You need to use the -K option of the OpenSSL command-line utility to pass in your 256 bit "key" (keys should consist of arbitrary bytes and not just printable ones). Keys are passed in hex encoded form. If you do that, then you also need to pass in a 128 bit IV through the -iv option.

Since your "key" is 256 bit (32 byte) long, then you need to specify aes-256-cbc.

Other problem:

OpenSSL uses PKCS#7 padding (synonymous to PKCS#5 padding) by default, but mcrypt pads the plaintext with zero to 15 0x00 bytes which is incompatible. Use the openssl extension in PHP which properly uses PKCS#7 padding.

Community
  • 1
  • 1
Artjom B.
  • 61,146
  • 24
  • 125
  • 222