使用OCB模式时Openssl解密失败

Openssl decryption fails when using OCB mode

我有一个 PHP 库,它是 Openssl 的包装器,其目标是默认情况下为新开发人员简化和安全地加密和解密数据。这个库成功地处理了许多不同的密码和模式,但我无法让 OCB 模式正常工作。

我似乎能够毫无问题地加密数据,但是当我尝试解密它时 openssl_decrypt() returns false。当我检查 openssl_error_string() 是否有任何错误消息时,有 none.

下面是一个 MVCE,演示了使用 AES-128-CBCAES-128-OCB 执行相同的代码。 AES-128-CBC 示例按预期工作。 AES-128-OCB 并没有说明它失败的原因。 (我在我的例子中特意使用了一个 16 个字符的纯文本字符串来从等式中删除空填充)。

$ciphers = [
    'AES-128-CBC',
    'AES-128-OCB'
];
$key = 'secretkey';
$plainText = 'Testing testing!';

foreach ($ciphers as $cipher) {
    printf('Cipher: %s%s', $cipher, PHP_EOL);
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length($cipher));
    printf('IV: %s%s', $iv, PHP_EOL);
    printf('Text: %s%s', $plainText, PHP_EOL);
    $encryptedText = openssl_encrypt($plainText, $cipher, $key, OPENSSL_RAW_DATA, $iv);
    printf('Encrypted Text: %s%s', $encryptedText, PHP_EOL);
    $encodedText = base64_encode($encryptedText);
    printf('Encoded Text: %s%s', $encodedText, PHP_EOL);
    $decodedText = base64_decode($encodedText);
    printf('Decoded Text: %s%s', $decodedText, PHP_EOL);
    $decryptedText = openssl_decrypt($decodedText, $cipher, $key, OPENSSL_RAW_DATA, $iv);
    printf('Decrypted Text: ');
    var_dump($decryptedText);
    while ($msg = openssl_error_string()) {
        printf('Openssl Error: %s%s', $msg, PHP_EOL);
    }
    printf('%s%s', str_repeat('-', 60), PHP_EOL);
}

输出:

Cipher: AES-128-CBC
IV: �K�K�l4.�4;y
Text: Testing testing!
Encrypted Text: vg��~6�D��R�����xd�^�,�[��p"~
Encoded Text: dgUIZ5itfjazRLTiUvzIxsjNeGScXqksjFsaq7pwIn4=
Decoded Text: vg��~6�D��R�����xd�^�,�[��p"~
Decrypted Text: string(16) "Testing testing!"
------------------------------------------------------------
Cipher: AES-128-OCB
IV: ��)����ƢX
Text: Testing testing!
Encrypted Text: m��i��B[�d�
Encoded Text: BW2IkWmo5kJbFgYf8YdkpQ==
Decoded Text: m��i��B[�d�
Decrypted Text: bool(false)
------------------------------------------------------------

我不是加密方面的专家,但在做这项工作的过程中学到了很多。我用谷歌搜索了 OCB 模式并让它与 PHP 和 Openssl 一起工作,但实际上没有关于这个主题的任何内容。

OCB is an authenticated encryption algorithm like GCM, i.e. during encryption a tag is generated which is used for authentication during decryption. OpenSSL supports OCB (here), whereby the implementation with the high level API is completely equivalent with GCM (here).

此 C 代码 returns 与发布的 PHP 代码相同 密文(假设明文、密钥和随机数相同)。但是,C 代码生成的标记 不是 PHP 代码生成的 。它既不会附加到密文,也不会像 GCM / CCM (here) 那样在第 6 个参数 ($tag) 中返回。后者甚至会导致错误消息(无法为不支持 AEAD 的密码提供经过身份验证的标签)。

2016 年 1 月的 PHP 错误报告 #67304 from May 2014 filed an identical bug for GCM (tag is not delivered although GCM is in the list of supported algorithms), which then led to the support of GCM and CCM in 7.1. (released December 2016). In the related PHP RFC OpenSSL AEAD support,可以在 未来范围 下阅读:添加对 OCB 模式的支持一旦扩展支持 OpenSSL 1.1.

总的来说,OCB 似乎在 PHP 中,可能只是尚未完全实现,就像当时的 GCM / CCM 一样,最终是一个错误。