openssl_encrypt返回false

时间:2017-01-31 08:04:56

标签: php encryption php-openssl

我正在尝试使用PHP中的openssl_encrypt加密字符串,但它一直返回FALSE。

$encrypted = openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PADDING, '1234123412341234');

我做错了什么?

3 个答案:

答案 0 :(得分:3)

在发布的答案之上,非常好,您提供的 输入参数的代码如下:

$plaintext = '1234';
$cipher = 'AES-256-CBC';
$key = 'this is a bad key';
$iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));

$encrypted = openssl_encrypt($plaintext, $cipher, $key, 0, $iv);

if(false === $encrypted)
{
    echo openssl_error_string();
    die;
}

$decrypted = openssl_decrypt($encrypted, $cipher, $key, 0, $iv);

$result = $decrypted === $plaintext;

print $result ? 'Everything is fine' : 'Well, we did not decrypt good, did we?';

编写完上述内容后,我建议不要使用,而是请使用经过测试的库,以便为您处理加密和解密的复杂性。

我建议使用defuse/php-encryption

答案 1 :(得分:0)

php > var_dump (openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PADDING, '1234123412341234'));
php shell code:1:
bool(false)
php > var_dump (openssl_error_string ());
php shell code:1:
string(94) "error:0607F08A:digital envelope routines:EVP_EncryptFinal_ex:data not multiple of block length"

您正在使用的密码似乎要求您加密的数据的长度是块长度的精确倍数。通过一些实验,我发现1234123412341234已成功加密。

我不知道这是否是所有openssl加密方案的通用功能,或者它是否是特定于某些方案的特定内容。在前一种情况下,您需要将输入填充到块大小的倍数。如果后者为真,则可以填充或切换到不对输入施加相同限制的其他加密方案。

对于填充,您需要找出所选密码的块大小(我不知道是否有openssl函数或常量为此提供),然后计算出你需要多少个字符填充您的输入字符串。

请注意,以下示例假定a)以某种方式以编程方式获取块大小(如果不是,那么您必须自己硬编码)和b)您正在工作使用面向字节的字符格式(unicode可能会导致问题!)

$plaintext = "Hello, I'm some plaintext!";
$blocksize = function_that_gets_a_blocksize_for_a_given_cypher ($cypher);
$strlen = strlen ($plaintext);
$pad = $blocksize - ($strlen % $blocksize);

// If the string length is already a multiple of the blocksize then we don't need to do anything
if ($pad === $blocksize) {
    $pad = 0;
}

$plaintext = str_pad ($plaintext, $strlen + $pad);

至于你的代码,这表明你需要在其中实现一些错误检测(但小心你实际记录/回显的错误检测的一部分!)。

$encrypted = openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PADDING, '1234123412341234');
if (false === $encrypted) {
    error_log ("Encryption failed! " . openssl_error_string ());
}

答案 2 :(得分:0)

  1. 由于AES等分组密码要求输入数据是块大小的精确倍数(AES为16字节),因此需要填充。通常的方法是通过将其作为选项传递来指定PKCS#7(néePKCS#5),并且填充将在加密时自动添加并在解密时删除。零填充(OPENSSL_ZERO_PADDING)是一个糟糕的解决方案,因为它不适用于二进制数据。

  2. IV需要是块大小,AES需要8个字节。不要依赖于填充的实现。

  3. 密钥应该是指定的确切大小,AES的有效块大小为128,192或256位(16,24或32字节)。不要依赖于填充的实现。