首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用AES-256-CCM在php中用python解密加密文本

如何使用AES-256-CCM在php中用python解密加密文本
EN

Stack Overflow用户
提问于 2020-05-13 18:18:45
回答 1查看 560关注 0票数 2

我试图用AES-256-CCM在python中使用cryptography.hazmat加密一个PHP中的密码文本,我在python代码中所做的是:

代码语言:javascript
复制
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)

然后,我将keynonceciphertext转换为base64

代码语言:javascript
复制
key_b64 = base64.standard_b64encode(key)
ciphertext_b64 = base64.standard_b64encode(ciphertext)
nonce_b64 = base64.standard_b64encode(nonce)

在我的例子中,我得到了这个结果

代码语言:javascript
复制
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'

我在我的base64代码中使用了结果

代码语言:javascript
复制
<?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/#/en/function.openssl-encrypt.html,我找不到另一个例子,解密过程不返回任何东西。

真正让我困惑的是:

  1. 我们没有在python代码中使用IV加密,但是PHP需要非NULL IV,如何解决这个问题?
  2. 在PHP和python中,$tag在PHP代码和$tag_lenght中都代表什么(密码=tag_length=8)?
  3. 如果解密需要nonce,如何在我的PHP代码中使用它?

怎么才能得到这份工作?从python加密并在PHP中解密相同的编码文本

备注:我必须使用python进行加密,使用php进行解密,我必须使用AES-CCM,python代码是固定的,谢谢您的理解。

谢谢

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-05-14 12:54:47

在用于AES-CCM的CCM中,似乎存在一个错误,即12字节的当前长度(由OP使用),这会导致错误的加密文本/标记。但是,OP的PHP代码中有许多缺陷隐藏了这个错误。因此,必须首先修复这些缺陷:

  • Python和PHP实现的不同之处在于,在Python代码中,密文和标记按这个顺序连接在一起,而在PHP代码中,密文和标记分别处理。
  • Python代码中的nonce对应于PHP代码中的IV。
  • 在encoded中,如果密文作为原始数据传递而不是Base64编码,则必须设置Base64标志。
  • 现在和密文(+ tag)的值在这两种代码中都不同。但是,更正是没有意义的,因为所选的12字节零值与PHP错误( 12字节)结合在一起,参见下面的内容。也就是说,成功测试的先决条件是不等于12个字节的当前大小。

考虑到这些点的PHP实现是。

代码语言:javascript
复制
<?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代码中解密数据,只要现在的长度不等于字节

Python实现允许一个长度为713字节(都包含在内)的为Python而来,s. 为Python而来。关于12字节的问题,如下所示:如果在12代码中,通过删除最后一个5字节,12字节被截断为7字节,则创建相同的密文/标记。下面的PHP代码说明了816字节的标记长度(PHPVersion7.4.4):

代码语言:javascript
复制
<?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不同的密码文本/标记(这就是为什么使用12字节的12字节的PHP代码失败的原因)。使用具有相同参数的Java/BC进行的检查会产生与Python相同的12字节的密码/标记,这将验证Python代码的值,并再次指出PHP实现中的一个bug。

编辑:我在这里提交了一个问题:https://bugs.php.net/bug.php?id=79601。注意:这个问题是由管理员设置为私有的,因此如果没有适当的权限s. 这里,就不能打开它(至少目前是这样)。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/61781987

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档