1 回答

TA貢獻(xiàn)1829條經(jīng)驗(yàn) 獲得超9個(gè)贊
AES-CCM 的 PHP 實(shí)現(xiàn)中似乎存在一個(gè)字節(jié)的隨機(jī)數(shù)長(zhǎng)度12
(由 OP 使用)的錯(cuò)誤,這會(huì)導(dǎo)致錯(cuò)誤的密文/標(biāo)簽。但是,此錯(cuò)誤被 OP 的 PHP 代碼中的許多缺陷所隱藏。因此,必須首先修復(fù)這些缺陷:
Python 和 PHP 實(shí)現(xiàn)的不同之處在于,在 Python 代碼中,密文和標(biāo)簽按此順序連接,而在 PHP 代碼中,密文和標(biāo)簽是分開(kāi)處理的。
Python 代碼中的 nonce 對(duì)應(yīng)于 PHP 代碼中的 IV。
在 PHP 代碼中,
OPENSSL_RAW_DATA
如果密文作為原始數(shù)據(jù)傳遞而不是 Base64 編碼,則必須設(shè)置標(biāo)志。nonce 和 ciphertext (+ tag) 的值在兩個(gè)代碼中不同。然而,由于選擇的 12 字節(jié)隨機(jī)數(shù)與 12 字節(jié)隨機(jī)數(shù)的 PHP 錯(cuò)誤相結(jié)合,更正毫無(wú)意義,請(qǐng)參見(jiàn)下文。即,成功測(cè)試的先決條件是隨機(jī)數(shù)大小不等于 12 字節(jié)。
考慮到這些要點(diǎn)的 PHP 實(shí)現(xiàn)是例如
<?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 的長(zhǎng)度不等于12bytes,就可以從 Python 代碼解密數(shù)據(jù)。
Python 和 PHP 實(shí)現(xiàn)允許長(zhǎng)度為7to13字節(jié)(包括兩者),s 的隨機(jī)數(shù)。這里是 Python。關(guān)于字節(jié) nonce 的問(wèn)題12,結(jié)果如下:如果在 PHP 代碼中通過(guò)刪除最后一個(gè)字節(jié)12將字節(jié) nonce 截?cái)酁樽止?jié),則會(huì)創(chuàng)建相同的密文/標(biāo)簽。以下 PHP 代碼針對(duì)和字節(jié)的標(biāo)記長(zhǎng)度說(shuō)明了這一點(diǎn)(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);
?>?
此結(jié)果表明 PHP 實(shí)現(xiàn)中存在錯(cuò)誤。
與 PHP 代碼相比,Python 代碼為12字節(jié)隨機(jī)數(shù)生成不同的密文/標(biāo)簽(這就是為什么(更正的)OP 的使用字節(jié)12隨機(jī)數(shù)的 PHP 代碼失敗的原因)。使用具有相同參數(shù)的 Java/BC 進(jìn)行的檢查會(huì)為字節(jié)隨機(jī)數(shù)生成與 Python 代碼相同的密文/標(biāo)簽,從而驗(yàn)證 Python 代碼的值并再次指示 PHP 實(shí)現(xiàn)中的錯(cuò)誤。12
- 1 回答
- 0 關(guān)注
- 261 瀏覽
添加回答
舉報(bào)