Reputation: 358
I'm trying to decrypt a file, I can decrypt it using OpenSSL in the terminal using the following string.
openssl -enc -d -aes-192-ecb -in file.crypt -out file -K 0123456789abcdef -iv 0
However, I want to decrypt this file in PHP. I have the following code:
$file = file_get_contents('file.crypt');
$key = 0123456789abcdef;
$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_192, $key, $file, MCRYPT_MODE_ECB);
print_r($data);
Obviously I'm missing something as the PHP script is returning data, but not the plain-text.
I have tried using MCRYPT_RIJNDAEL_128 but with no luck. Please let me know if you can see what I'm doing wrong. Thanks in advance.
UPDATE
I have successfully decrypted my file using the following:
$key = pack('H*', '0123456789abcdef'); //In >= PHP 5.4 you can use hex2bin() I think.
$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $file, MCRYPT_MODE_ECB);
Upvotes: 2
Views: 4390
Reputation: 102205
openssl -enc -d -aes-192-ecb -in file.crypt -out file -K 0123456789abcdef -iv 0
Specify your key in a keyfile with -kfile
, and not on the command line with -K
.
Maybe I'm reading the sources of <openssl dir>/apps/enc.c
wrong, but it looks broke to me when using the -K
option.
First, there is a declaration for hex encoded values from the command line (line 114):
char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
Next, hkey
is populated from the command line (line 265);
else if (strcmp(*argv,"-K") == 0)
{
if (--argc < 1) goto bad;
hkey= *(++argv);
}
Then, a few tests are performed. First, line 422:
if ((str == NULL) && (cipher != NULL) && (hkey == NULL))
{
...
EVP_read_pw_string(...)
...
}
And then line 581:
if ((hkey != NULL) && !set_hex(hkey,key,sizeof key))
{
BIO_printf(bio_err,"invalid hex key value\n");
goto end;
}
Then nothing else is done with hkey
.
Now, following the kfile
option looks much more interesting:
else if (strcmp(*argv,"-kfile") == 0)
{
static char buf[128];
FILE *infile;
char *file;
/* lots of reading and parsing removed */
...
str=buf;
}
After the key is assigned to str
, something is done with it:
if (cipher != NULL)
{
/* Note that str is NULL if a key was passed on the command
* line, so we get no salt in that case. Is this a bug?
*/
if (str != NULL)
{
/* Salt handling: if encrypting generate a salt and
* write to output BIO. If decrypting read salt from
* input BIO.
*/
unsigned char *sptr;
if(nosalt) sptr = NULL;
else
{
if(enc) {
if(hsalt) {
if(!set_hex(hsalt,salt,sizeof salt)) {
BIO_printf(bio_err, "invalid hex salt value\n");
goto end;
}
} else if (RAND_pseudo_bytes(salt, sizeof salt) < 0)
goto end;
...
EVP_BytesToKey(cipher,dgst,sptr,
(unsigned char *)str,
strlen(str),1,key,iv);
Here's a small debugging session with a write watchpoint on key
. Its not written when using the -K
option (though it is used in some EVP_*
functions):
(gdb) b main
Breakpoint 1 at 0x1000071c0: file enc.c, line 106.
(gdb) watch key@16
Hardware watchpoint 3: {<data variable, no debug info>} 140735109990496 @ 16
(gdb) r -d -aes-192-ecb -in file.crypt -out file.txt -K 0123456789abcdef -iv 0
Starting program: .../openssl-1.0.1e/apps/enc.exe -d -aes-192-ecb -in file.crypt
-out apps.c -K 0123456789abcdef -iv 0
Breakpoint 1, main (argc=11, argv=0x7fff5fbff970) at enc.c:106
106 char *strbuf=NULL;
(gdb) c
Continuing.
Program exited normally.
Just bike shedding here: aes-192-ecb
and MCRYPT_MODE_ECB
is only secure if you don't reuse keys and the file is 16 bytes or less. As soon as you reuse the key or exceed 16 bytes, you loose PRP-security.
Upvotes: 1
Reputation: 93948
The keys and IV in openssl
are in hexadecimals (and therefore too short) and those in PHP are used as character values. Please specify 32, 48 or 64 hexadecimal digits for AES keys in openssl and the same value in 16, 24 or 32 bytes in PHP. The IV should always be 32 hex digits or 16 bytes as that is the block size of AES.
You should always use MCRYPT_RIJNDAEL_128
as the 128 in there is the block size - not the key size - of the algorithm, The MCRYPT_RIJNDAEL_192
and MCRYPT_RIJNDAEL_256
algorithms do not implement AES.
Also, openssl defaults to PKCS#7 padding, check the mcrypt_encrypt
comments section for implementation of PKCS padding for PHP - it does not provide it by default.
Upvotes: 4