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 關注
- 255 瀏覽
添加回答
舉報