Php openssl\u encrypt返回false

Php openssl\u encrypt返回false,php,encryption,php-openssl,Php,Encryption,Php Openssl,我试图在PHP中使用openssl_encrypt对字符串进行加密,但它总是返回FALSE $encrypted = openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PADDING, '1234123412341234'); 我做错了什么 php > var_dump (openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PA

我试图在PHP中使用openssl_encrypt对字符串进行加密,但它总是返回FALSE

$encrypted = openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PADDING, '1234123412341234');
我做错了什么

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"
似乎您正在使用的密码要求您正在加密的数据的长度是块长度的精确倍数。通过一些实验,我发现
12341234112341234
已成功加密

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

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

请注意,下面的示例假设a)有某种方法可以通过编程获得块大小(如果没有,则您必须自己硬编码),b)您使用的是面向字节的字符格式(unicode可能会导致问题!)

至于您的代码,这表明您需要在代码中实现一些错误检测(但是要小心,作为错误检测的一部分,您实际记录/回显了什么!)

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

  • IV需要为块大小,AES为8字节。不要依赖于实现进行填充

  • 密钥应为指定的精确大小,AES的有效块大小为128、192或256位(16、24或32字节)。不要依赖于实现进行填充


  • 在发布的答案(这些答案非常好)之上,考虑到您的输入参数,您需要的代码如下:

    $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?';
    
    写了以上内容后,我建议不要使用它,相反,请使用经过测试的库来处理加密和解密的复杂性。
    我建议使用

    IV需要16个字节。什么是OpenSSL?可能是相关的。通常我的第一个建议是“阅读文档”,但事实证明,openssl\u encrypt的PHP文档非常糟糕,几乎不存在。您可以使用
    openssl\u error\u string()
    来找出到底出了什么问题。您还可以使用来计算所选密码的初始化向量的长度。使用这两种方法,更容易判断出哪里出了问题。
    $encrypted = openssl_encrypt('1234', 'AES-256-CBC', 'kGJeGF2hEQ', OPENSSL_ZERO_PADDING, '1234123412341234');
    if (false === $encrypted) {
        error_log ("Encryption failed! " . openssl_error_string ());
    }
    
    $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?';