【问题标题】:Decrypting data with openssl commandline tool使用 openssl 命令行工具解密数据
【发布时间】:2012-06-25 00:33:47
【问题描述】:

我必须遵循代码,据我所知它是正确的,但它不起作用。我正在尝试使用 PHP 的 Mcrpyt 对数据进行编码,然后使用 openssl 命令行工具对其进行解码。

这是我的 PHP 代码:

/*
 * Convert a normal ascii string to a hexadecimal string.
 * Complement of hexToString().
*/
function stringToHex($str)
{
    $hex_str = "";
    for ($i = 0; $i < strlen($str); ++$i)
    {
        $hex_str .= sprintf("%02X", ord($str[$i]));
    }

    return $hex_str;
}


    $iv = mcrypt_create_iv(mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM);

    $block_size = mcrypt_get_block_size("rijndael-128", "cbc");
    $pad = $block_size - (strlen($data) % $block_size);
    $data .= str_repeat(chr($pad), $pad);

    $encrypted = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, "1234567812345678", $data, MCRYPT_MODE_CBC, $iv);

    $message = stringToHex($iv) . base64_encode($encrypted);

我将 IV 附加到编码的消息中。比如说IV是00000000000000000000000000000000(大小为32),然后我使用以下命令进行解密:

openssl enc -d -aes-128-cbc -A -nosalt -K 31323334353637383132333435363738 -iv 00000000000000000000000000000000 -in file_in > file_out

另请注意,1234567812345678 是十六进制,即 31323334353637383132333435363738。但我不断收到相同的错误消息:

错误的解密 1340:错误:0606506D:数字信封例程:EVP_DecryptFinal_ex:错误的最终块长度:./crypto/evp/evp_enc.c:454:

有人吗?

提前致谢, 全部的爱, 乔里。

【问题讨论】:

  • 没有人? :-( 还在等待答案。
  • 好吧,你应该写一个独立的代码示例。缺少的 stringToHex 函数可能很明显,但不允许测试您的代码。
  • 哦,是的,我很抱歉。会编辑。但我不认为有问题,因为它会生成适当的 IV。不管怎么说,还是要谢谢你! :-)

标签: php openssl mcrypt rijndael


【解决方案1】:

openssl enc 使用您实现的 PKCS#5 填充,如果数据是块大小的倍数,则强制填充块除外。由于您使用 16 个字节(即块大小)进行测试,因此您需要添加另外 16 个包含 chr(16) 的字节。

【讨论】:

    【解决方案2】:

    好吧,我测试了您的代码,并进行了一些更改。

    1) openssl 的输入应仅包括密文,而不是前置 IV(因为您的代码不完整,我不确定您是否确实在使用 openssl 处理密文之前从密文中剥离了 IV)。

    2) 您的 openssl 命令缺少实际执行 Base64 解码所需的参数 (-a)(仅使用 -A 不会启用此功能)。同样,由于您的描述不完整,我不确定您是否确实在将消息存储到 file_in 之前对其进行了 Base64 解码。

    为了完整起见,这是我用来测试您的代码的代码(我从命令行运行它,而不是使用 Web 服务器)。

    <?php
    
    $data = "
    This is a test. This is only a test.
    Stack Overflow is collaboratively built and maintained
    by your fellow programmers.
    ";
    $keybin = "1234567812345678";
    
    
    //$iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_DEV_RANDOM);
    $iv = mcrypt_create_iv (mcrypt_get_iv_size (MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC), MCRYPT_RAND);
    $block_size = mcrypt_get_block_size ("rijndael-128", "cbc");
    $pad = $block_size - (strlen ($data) % $block_size);
    $data .= str_repeat (chr ($pad), $pad);
    $encrypted = mcrypt_encrypt (MCRYPT_RIJNDAEL_128, $keybin, $data, MCRYPT_MODE_CBC, $iv);
    $message = base64_encode ($encrypted);
    
    echo "CIPHERTEXT=  " . $message . "\n";
    echo "IV=  " . bin2hex ($iv) . "\n";
    echo "KEY=  " . bin2hex ($keybin) . "\n";
    
    echo "\nTest with:\n\necho $message | openssl enc -d -aes-128-cbc -nosalt -a -A -K " . bin2hex ($keybin) . " -iv " . bin2hex ($iv) . "\n\n";
    
    ?>
    

    其他细微差别是我使用了 PHP 的 bin2hex。

    它将产生如下输出:

    CIPHERTEXT=  /e81Ua/0jxgff3j5GjKXaNilv5WqPYV7yRYy4AzsTUmGQeK0hcMjuUYp1Yrfthaox9zTI0DeDQT4fba+y/qTQahZpYRAKcZa209RVg4W1HrySfZPMRCxE+y8r8scL3Xmj+oMGFpS+cDo111OPqwHhNwWSHbMlsoJLvMr70ZiQmE=
    IV=  56c7c7248c68127cee8f0e54d89b4fc1
    KEY=  31323334353637383132333435363738
    
    Test with:
    
    echo /e81Ua/0jxgff3j5GjKXaNilv5WqPYV7yRYy4AzsTUmGQeK0hcMjuUYp1Yrfthaox9zTI0DeDQT4fba+y/qTQahZpYRAKcZa209RVg4W1HrySfZPMRCxE+y8r8scL3Xmj+oMGFpS+cDo111OPqwHhNwWSHbMlsoJLvMr70ZiQmE= | openssl enc -d -aes-128-cbc -nosalt -a -A -K 31323334353637383132333435363738 -iv 56c7c7248c68127cee8f0e54d89b4fc1
    

    您遇到的错误(错误的解密、数字信封例程 EVP_DecryptFinal_ex)通常意味着错误的密钥或损坏的密文。我认为在您的示例中,问题是由前缀 IV 和/或缺少 Base64 解码引起的损坏的密文。

    【讨论】:

    • 非常感谢!问题在于我认为 -A 意味着 base64 解码一行。将其更改为 -a -A 解决了问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 2019-12-30
    • 2016-10-06
    • 2015-11-27
    • 1970-01-01
    • 2016-06-05
    相关资源
    最近更新 更多