我正在尝试解密文件,我可以使用以下字符串在终端中使用OpenSSL对其进行解密。
openssl -enc -d -aes-192-ecb -in file.crypt -out file -K 0123456789abcdef -iv 0
但是,我想用PHP解密这个文件。我有以下代码:
$file = file_get_contents('file.crypt');
$key = 0123456789abcdef;
$data = mcrypt_decrypt(MCRYPT_RIJNDAEL_192, $key, $file, MCRYPT_MODE_ECB);
print_r($data);
显然我错过了一些东西,因为PHP脚本正在返回数据,而不是纯文本。
我尝试过使用MCRYPT_RIJNDAEL_128,但没有运气。如果你能看到我做错了什么,请告诉我。提前谢谢。
更新
我已使用以下内容成功解密了我的文件:
$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);
答案 0 :(得分:4)
openssl
中的键和IV是十六进制(因此太短),PHP中的键和IV用作字符值。请在openssl中为AES密钥指定32,48或64个十六进制数字,在PHP中为16,24或32字节指定相同的值。 IV应始终为32个十六进制数字或16个字节,因为这是AES的块大小。
您应该始终使用MCRYPT_RIJNDAEL_128
作为128,因为算法的块大小(而不是密钥大小),MCRYPT_RIJNDAEL_192
和MCRYPT_RIJNDAEL_256
算法不< / em>实施AES。
此外,openssl默认使用PKCS#7填充,检查mcrypt_encrypt
注释部分是否实现了PHP的PKCS填充 - 它默认情况下不提供它。
答案 1 :(得分:1)
openssl -enc -d -aes-192-ecb -in file.crypt -out file -K 0123456789abcdef -iv 0
使用-kfile
在密钥文件中指定密钥,而不是在-K
的命令行中指定。
也许我正在阅读<openssl dir>/apps/enc.c
错误的来源,但在使用-K
选项时看起来很糟糕。
首先,命令行(第114行)有一个十六进制编码值的声明:
char *hkey=NULL,*hiv=NULL,*hsalt = NULL;
接下来,从命令行填充hkey
(第265行);
else if (strcmp(*argv,"-K") == 0)
{
if (--argc < 1) goto bad;
hkey= *(++argv);
}
然后,进行一些测试。第一,第422行:
if ((str == NULL) && (cipher != NULL) && (hkey == NULL))
{
...
EVP_read_pw_string(...)
...
}
然后第581行:
if ((hkey != NULL) && !set_hex(hkey,key,sizeof key))
{
BIO_printf(bio_err,"invalid hex key value\n");
goto end;
}
然后hkey
没有其他任何事情。
现在,遵循kfile
选项看起来更有趣:
else if (strcmp(*argv,"-kfile") == 0)
{
static char buf[128];
FILE *infile;
char *file;
/* lots of reading and parsing removed */
...
str=buf;
}
将密钥分配给str
后,可以使用它完成某些操作:
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);
以下是key
上write watchpoint的小型调试会话。使用-K
选项时不会写入它(尽管它在某些EVP_*
函数中使用):
(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.
这里只是自行车脱落:aes-192-ecb
和MCRYPT_MODE_ECB
只有在您不重复使用密钥且文件不超过16个字节时才是安全的。一旦重复使用密钥或超过16个字节,就会失去PRP安全性。