1 回答
TA贡献1829条经验 获得超9个赞
AES-CCM 的 PHP 实现中似乎存在一个字节的随机数长度12
(由 OP 使用)的错误,这会导致错误的密文/标签。但是,此错误被 OP 的 PHP 代码中的许多缺陷所隐藏。因此,必须首先修复这些缺陷:
Python 和 PHP 实现的不同之处在于,在 Python 代码中,密文和标签按此顺序连接,而在 PHP 代码中,密文和标签是分开处理的。
Python 代码中的 nonce 对应于 PHP 代码中的 IV。
在 PHP 代码中,
OPENSSL_RAW_DATA
如果密文作为原始数据传递而不是 Base64 编码,则必须设置标志。nonce 和 ciphertext (+ tag) 的值在两个代码中不同。然而,由于选择的 12 字节随机数与 12 字节随机数的 PHP 错误相结合,更正毫无意义,请参见下文。即,成功测试的先决条件是随机数大小不等于 12 字节。
考虑到这些要点的 PHP 实现是例如
<?php
// Data from Python code
$key_from_python = base64_decode('<Base64 encoded key from Python>');
$ciphertext_from_python = base64_decode('<Base64 encoded (ciphertext + tag) from Python>');
$nonce_from_python = base64_decode('<Base64 encoded nonce from Python>');
$cipher = 'aes-256-ccm';
// Separate ciphertext and tag
$tagLength = 8;
$ciphertext = substr($ciphertext_from_python, 0, -$tagLength);
$tag = substr($ciphertext_from_python, -$tagLength);
// Decrypt
if (in_array($cipher, openssl_get_cipher_methods())){
$decrypted_mesage_from_pythom = openssl_decrypt($ciphertext, $cipher, $key_from_python, OPENSSL_RAW_DATA, $nonce_from_python, $tag);
echo $decrypted_mesage_from_pythom;
}
?>
使用此 PHP 代码,只要 nonce 的长度不等于12bytes,就可以从 Python 代码解密数据。
Python 和 PHP 实现允许长度为7to13字节(包括两者),s 的随机数。这里是 Python。关于字节 nonce 的问题12,结果如下:如果在 PHP 代码中通过删除最后一个字节12将字节 nonce 截断为字节,则会创建相同的密文/标签。以下 PHP 代码针对和字节的标记长度说明了这一点(PHP 版本 7.4.4):75816
<?php
function printCiphertextTag($plaintext, $key, $iv, $taglength){
$encrypted = openssl_encrypt($plaintext, "aes-256-ccm", $key, OPENSSL_RAW_DATA, $iv, $tag, NULL, $taglength);
echo sprintf("tag size: %2s, IV size: %2s, IV (hex): %-' 24s, ciphertext (hex): %s, tag (hex): %s\n", $taglength, strlen($iv), bin2hex($iv), bin2hex($encrypted), bin2hex($tag));
}
$plaintext = 'message from python';
$key = '01234567890123456789012345678901';
$nonce12 = openssl_random_pseudo_bytes(12);
$nonce7 = substr($nonce12, 0, 7);
printCiphertextTag($plaintext, $key, $iv = $nonce12, $taglength = 8);
printCiphertextTag($plaintext, $key, $iv = $nonce7, $taglength = 8);
printCiphertextTag($plaintext, $key, $iv = $nonce12, $taglength = 16);
printCiphertextTag($plaintext, $key, $iv = $nonce7, $taglength = 16);
?>
此结果表明 PHP 实现中存在错误。
与 PHP 代码相比,Python 代码为12字节随机数生成不同的密文/标签(这就是为什么(更正的)OP 的使用字节12随机数的 PHP 代码失败的原因)。使用具有相同参数的 Java/BC 进行的检查会为字节随机数生成与 Python 代码相同的密文/标签,从而验证 Python 代码的值并再次指示 PHP 实现中的错误。12
- 1 回答
- 0 关注
- 218 浏览
添加回答
举报