繁体   English   中英

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

[英]how to decrypt in php an encrypted text by python using AES-256-CCM

我试图解密 PHP 中的密文,该密文使用 python 中的 cryptography.hazmat 使用AES-256-CCM cryptography.hazmat ,我在 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)

然后我将keynonceciphertext转换为 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/#/en/function.openssl-encrypt.html并且我找不到另一个示例解密过程不返回任何内容
真正让我困惑的是:

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

如何得到这份工作? 从 python 加密并解密 PHP 中的相同密文

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

谢谢你

AES-CCM 的 PHP 实现中似乎存在一个错误,其随机数长度为12个字节(由 OP 使用),导致密文/标签错误。 但是,此错误被 OP 的 PHP 代码中的许多缺陷所隐藏。 因此,必须首先修复这些缺陷:

  • The Python and PHP implementations differ in that in the Python code the ciphertext and tag are concatenated in that order, whereas in the PHP code the ciphertext and tag are processed separately.
  • Python 代码中的 nonce 对应于 PHP 代码中的 IV。
  • 在 PHP 代码中,如果密文作为原始数据而不是 Base64 编码传递,则必须设置OPENSSL_RAW_DATA标志。
  • 随机数和密文(+ 标记)的值在两种代码中不同。 但是,由于选择的 12 字节 nonce 与 PHP 错误结合使用 12 字节 nonce,因此更正是没有意义的,见下文。 即成功测试的先决条件是nonce 大小不等于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 的长度不等于12字节,就可以从 Python 代码中解密数据。

Python 和 PHP 实现允许随机数长度为713个字节(包括两个字节),s。 这里是 Python 关于12字节随机数的问题,结果如下:如果在 PHP 代码中,通过删除最后5个字节将12字节随机数截断为7个字节,则创建相同的密文/标签。 以下 PHP 代码说明了标签长度为816字节(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 实现中存在错误。

相比之下,与 PHP 代码相比,Python 代码为12 12字节的 nonce 生成不同的密文/标签(这就是为什么(更正的)OP 的 Z2FEC392304A5C23AC138DA228DAB7CZ 代码失败的原因)。 使用相同参数对 Java/BC 进行检查会为12字节随机数生成与 Python 代码相同的密文/标签,该代码验证 Python 代码的值,并再次表明 Z2FEC392304A792C 实现中的错误。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM