如何使用AES-256-CCM在php中解密python加密的文本
我正在尝试用PHP解密一条chiphertext,它是用python中的如何使用AES-256-CCM在php中解密python加密的文本,python,php,cryptography,aes,Python,Php,Cryptography,Aes,我正在尝试用PHP解密一条chiphertext,它是用python中的cryptography.hazmat用AES-256-CCM加密的 我在python代码中所做的是: from cryptography.hazmat.primitives.ciphers.aead import AESCCM from os import urandom import base64 #Text To Encrypt plaintext = bytes("message from python", enc
cryptography.hazmat
用AES-256-CCM
加密的
我在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)
然后我将键
、nonce
和密文
转换为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;
}
AES-CCM的PHP实现中似乎存在一个错误,当前长度为12
字节(由OP使用),这会导致错误的密文/标记。然而,OP的PHP代码中的许多缺陷隐藏了这个bug。因此,必须首先修复这些缺陷:
- Python和PHP实现的不同之处在于,在Python代码中,密文和标记按顺序连接,而在PHP代码中,密文和标记分别处理
- Python代码中的nonce对应于PHP代码中的IV
- 在PHP代码中,如果密文作为原始数据传递而不是Base64编码,则必须设置
OPENSSL_RAW_DATA
标志
- nonce和ciphertext(+tag)的值在两种代码中都不同。然而,由于选择了12字节的nonce,加上12字节nonce的PHP错误,因此更正是没有意义的,请参见下文。即,成功测试的先决条件是一个不等于12字节的nonce大小
考虑到这些点的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代码为12
字节的nonce与PHP代码生成不同的密文/标记(这就是为什么(更正的)OP的PHP代码使用12
字节的nonce失败的原因)。使用具有相同参数的Java/BC进行检查会为12
字节的nonce生成与Python代码相同的密文/标记,这将验证Python代码的值,并再次表明PHP实现中存在错误
编辑:我在这里提交了一个问题:。注意:该问题由管理员设置为私有,因此在没有适当权限的情况下无法打开(至少目前是这样) 您的PHP代码充满了如此多的错误,如此多的数据被误译或完全破坏,以至于无法提供任何有用的信息。有一件事我可以肯定地说,你需要在PHP中打开错误报告,这样你就可以看到你的代码生成的错误页面。如果我全部在PHP中进行解密和加密,则解密和加密工作正常,但如果我尝试用python解密加密的内容,则无法工作,关于数据,我将所有内容转换为base64,以避免丢失数据,是的,错误报告已打开,没有错误报告。请告诉我php中的错误是什么,至少是主要错误。您运行的php必须与您发布的非常不同。我敢打赌python中的nonce
就是PHP中的iv
。如果您想看到错误,只需复制/粘贴您发布的PHP并尝试运行它。变量被使用但未初始化,变量名中的输入错误,密文和nonce完全被错误转录,甚至在修复了密文长度不正确的问题后。如果你仔细阅读了我的问题,你会很清楚我在寻找什么,问题是,在python中我们有nonce
ciphertext
但是在PHP中它需要$tag
和$IV
$ciphertext
和可选的$tag\u length
,如果nonce
被错误转录,你能给我一个更好的方法在PHP中重用吗,它给你错误的原因是它需要定义$tag
,这就是为什么我首先问这个问题,tag代表什么,如果你把IV
当作nonce
什么是tag
,那么如果你把tag
当作nonce
我们该怎么办呢?
<?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);
?>