使用openssl命令行工具解密数据

时间:2012-06-22 16:57:27

标签: php openssl mcrypt rijndael

我必须遵循代码,据我所知它是正确的,但它不起作用。我试图用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:

任何?

提前致谢, 全部的爱, JORI。

2 个答案:

答案 0 :(得分:2)

好吧,我测试了你的代码,它有一些改变。

1)openssl的输入应该只包括密文,而不是前面的IV(因为你的代码不完整我不确定你是否确实在用openssl处理它之前从密文中删除了IV)。

2)你的openssl命令缺少一个参数(-a),实际进行Base64解码所需(只使用-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解码而导致的密文损坏。

答案 1 :(得分:1)

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