我试图在PHP中解密一个用以下方法加密的芯片文本。AES-256-CCM
使用 cryptography.hazmat
在python中,我在我的python代码中做的是。
from cryptography.hazmat.primitives.ciphers.aead import AESCCM
from os import urandom
import base64
#Text To Encrypt
plaintext = bytes("message from python", encoding='utf-8')
#AES 256 Key Genrator
key = AESCCM.generate_key(256)
#Genrate Nonce
nonce= urandom(12)
#chipher
cipher = AESCCM(key, tag_length=8)
#Encryption
ciphertext = cipher.encrypt(nonce, plaintext, None)
然后我把 key
, nonce
和 ciphertext
到base64
key_b64 = base64.standard_b64encode(key)
ciphertext_b64 = base64.standard_b64encode(ciphertext)
nonce_b64 = base64.standard_b64encode(nonce)
在我的例子中,我得到了这样的结果
key = b'\xcb\x14\x96{,0(\x15\x86 \xda\xf8\x1b"i|M\xbd\xc5d\xe7\xa6I\xdf\x7f\xe11\xae\xe8\x8a\xb3j'
key_b64 = b'yxSWeywwKBWGINr4GyJpfE29xWTnpknff+ExruiKs2o='
nonce = b'\xc7f\xdc\xe3\xe4\x03>M\x9by\x92\x9d
nonce_b64 = b'x2bc4+QDPk2beZKd'
ciphertext = b'R\x9f\xe6D\\_\xdexC\x82\xf8\x8e\x9b;\x91\xc7OLo\xc2\t/\x8fV>G='
ciphertext_b64 = b'Up/mRFxf3nhDgviOmzuRx09Mb8IJL49WPkc9'
我在我的PHP代码中使用base64的结果
<?php
$key_from_python = base64_decode('yxSWeywwKBWGINr4GyJpfE29xWTnpknff+ExruiKs2o=');
$ciphertext_from_python = base64_decode('ooGUzo0YiwKPs9+2wXySYEpdBNfSpyLUHm1M');
$nonce_from_python = base64_decode('Up/x2bc4+QDPk2beZKd');
$cipher = "aes-256-ccm";
if (in_array($cipher, openssl_get_cipher_methods())){
$ivlen = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($ivlen);
$decrypted_mesage_from_pythom =
openssl_decrypt($encrypted_from_python_,$cipher,$key_from_python,$options=0 , $iv, $tag);
echo $decrypted_mesage_from_pythom;
}
其基于一个例子,我发现这里 http:/php.babo.ist#enfunction.openssl-encrypt.html。 我找不到另一个例子,解密过程中没有返回任何东西,真正让我困惑的是。
$tag
在PHP代码中表示,$tag_lenght在PHP和python(cipher = AESCCM(key, tag_length=8)) ?nonce
如何在我的PHP代码中使用它?如何让这个工作? 从python中加密,并在PHP中解密相同的芯片文本。
注 说明:我必须使用python进行加密,php进行解密,我必须使用AES-CCM,python的代码是固定的,谢谢你的理解。
谢谢
在PHP实现中,似乎有一个错误,对于非ce长为 12
字节(OP使用的),导致密码文本标签错误。然而,这个错误被OP的PHP代码中的一些缺陷所隐藏。因此,必须先修复这些缺陷。
OPENSSL_RAW_DATA
如果密文是作为原始数据而非 Base64 编码传递的,则必须设置该标志。一个考虑到这些因素的 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代码,我们可以从Python代码中解密数据 只要nonce的长度不等于 12
字节数.
Python和PHP的实现允许一个长度为 7
到 13
字节 (都包括在内), s. 此处为Python. 关于这个问题 12
字节的nonce,结果如下。如果在PHP代码中 12
字节的 nonce 被截断为 7
通过删除最后一个 5
字节数, 一样 ciphertexttag被创建。下面的PHP代码说明了以下标签长度的情况 8
和 16
字节(PHP版本7.4.4)。
<?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 实现中的一个错误。
与此相反,Python代码会对不同的 12
与PHP代码相比,字节数为nonce(这就是为什么(修正后的)OP的PHP代码使用了一个 12
字节nonce失败)。) 用相同参数的JavaBC检查会产生以下结果 一样 的密文标记 12
bytes nonce作为Python代码,验证了Python代码的值,再次说明PHP实现中的一个bug。
EDIT:我已经在这里提交了一个问题。https:/bugs.php.netbug.php?id=79601. 注: 该问题已确定为: 私人 由管理员管理,所以如果没有相应的权限就无法打开(至少目前是这样),s。这里的.