使用OpenSSL解密字符串在终端中工作,但不在PHP脚本中工作

时间:2014-01-12 00:18:21

标签: php encryption openssl

我正在尝试解密文件,我可以使用以下字符串在终端中使用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);

2 个答案:

答案 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_192MCRYPT_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);

以下是keywrite 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-ecbMCRYPT_MODE_ECB只有在您不重复使用密钥且文件不超过16个字节时才是安全的。一旦重复使用密钥或超过16个字节,就会失去PRP安全性。