我运行的是 PHP 7.2.8。根据
openssl_get_cipher_methods
chacha20-poly1305 是受支持的算法:
echo in_array('chacha20-poly1305', openssl_get_cipher_methods()) ? 'yes' : 'no';
输出“是”。
所以我尝试使用
chacha20-poly1305
:
$plaintext = 'zzzzzz';
$key = str_repeat('k', 32);
$nonce = str_repeat('n', 12);
$aad = '';
$r = openssl_encrypt(
$plaintext,
'chacha20-poly1305',
$key,
OPENSSL_RAW_DATA,
$nonce,
$newtag,
$aad
);
echo bin2hex($r);
输出 PHP 警告:
警告:openssl_encrypt():无法为不支持 AEAD 的密码提供经过身份验证的标签
$r
是 f4854428b8a8
。
我能够使用
r
获得与 chacha20
相同的输出(即通过这样做没有 poly1305
):
$r = openssl_encrypt(
$plaintext,
'chacha20',
$key,
OPENSSL_RAW_DATA,
"\1\0\0\0" . $nonce
);
输出相同的事实意味着 Poly1305 身份验证代码既没有附加到密文中,也没有添加到密文前面。
我的问题是...如何在 PHP 中使用 OpenSSL 获取 Poly1305 身份验证代码?
另外,我知道 libsodium 提供了 chacha20-poly1305 支持,但我仍然很好奇它如何与 OpenSSL 一起使用。
OpenSSL 的问题仍未解决(2020 年 11 月),因此如果您需要使用 ChaCha20-Poly1305 使用 PHP 进行身份验证加密 我推荐该库 Leigh (https://github.com/lt/PHP-AEAD-ChaCha20-Poly1305) 可以实现 非常简单。
auth-tag ($tag) 附加在密文后面,需要先分离出来 开始解密。
请注意,我正在使用 OpenJDK 11 (Java) 测试相同的功能:两个函数都会生成相同的密文,但不同的身份验证标签,因此它们在跨平台环境中不可用。
输出:
ChaCha20-Poly1305 encryption with leigh/aead-chacha20-poly1305
tag (16 bytes long, Base64): FK11WpqxhDuJytSgHN86tQ==
ciphertext (Base64): 1rXNtbeGF9KsMZXgPjszIeJ0Ze5ua+Uh5Aexu1ngaH4XoeldG71DwuDEAA==
decrypt: The quick brown fox jumps over the lazy dog
代码(安全警告:切勿在生产中使用静态密钥或随机数):
<?php
# make sure that you used Composer to get "leigh/aead-chacha20-poly1305"
require __DIR__ . '/vendor/autoload.php';
// ### never use static key & nonce in production, this is for testing only ###
$key = '12345678901234567890123456789012'; // 32 bytes
$nonce = '123456789012'; // 12 bytes
$plaintext = 'The quick brown fox jumps over the lazy dog';
$aad = '';
echo 'ChaCha20-Poly1305 encryption with leigh/aead-chacha20-poly1305' . PHP_EOL;
list($ciphertext, $tag) = \ChaCha20Poly1305\encrypt($key, $nonce, $aad, $plaintext);
echo 'tag (16 bytes long, Base64): ' . base64_encode($tag) . PHP_EOL;
echo 'ciphertext (Base64): ' . base64_encode($ciphertext) . PHP_EOL;
$decrypt = \ChaCha20Poly1305\decrypt($key, $nonce, $aad, $ciphertext, $tag);
echo 'decrypt: ' . $decrypt . PHP_EOL;
?>
PHP 8.2 添加了对 chacha20-poly1305 的 AEAD 支持。
我使用以下代码对其进行了测试,该代码与问题中显示的代码相同,只是它还打印了 AEAD 标签。
$plaintext = 'zzzzzz';
$key = str_repeat('k', 32);
$nonce = str_repeat('n', 12);
$aad = '';
$r = openssl_encrypt($plaintext, 'chacha20-poly1305', $key, OPENSSL_RAW_DATA, $nonce, $tag, $aad);
echo bin2hex($r), "\n", bin2hex($tag), "\n";
我得到的输出如下。
$ php test_chacha20.php
f4854428b8a8
0a0f1fab235b365765364a61e1bb68ff
没有打印任何警告。