如何使用AES-256-CCM通过python在php中解密加密的文本 [英] how to decrypt in php an encrypted text by python using AES-256-CCM

查看:203
本文介绍了如何使用AES-256-CCM通过python在php中解密加密的文本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

im trying to decrypt a chiphertext in PHP that was encrypted with AES-256-CCM using cryptography.hazmat in python what i did in my python code is :

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

then i convert the key , nonce and ciphertext to base64

key_b64 = base64.standard_b64encode(key)
ciphertext_b64 = base64.standard_b64encode(ciphertext)
nonce_b64 = base64.standard_b64encode(nonce)

le我得到了这个结果

in my example i got this results

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结果

i use the base64 results in my PHP code

<?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 并且我找不到另一个示例
解密过程没有返回任何内容

,真正让我感到困惑的是:

its based on an example that i find here http://php.babo.ist/#/en/function.openssl-encrypt.html and i cant find another example the decryption processes dose not return anything
and what really confusing me is :


  1. 我们没有使用IV加密python代码,但是PHP需要
    非NULL IV,如何解决呢?

  2. <$ c $是什么c> $ tag 代表PHP代码,$ tag_lenght代表PHP和
    python(cipher = AESCCM(key,tag_length = 8))吗?

  3. 如果解密需要 nonce 如何在我的PHP代码中使用它?

  1. we didn't use IV to encrypt in python code but the PHP need non-NULL IV ,how to solve that ?
  2. what $tag represent in PHP code and $tag_lenght both in PHP and python(cipher = AESCCM(key, tag_length=8)) ?
  3. if the decryption need nonce how to use it in my PHP code ?

如何进行这项工作?从python加密并在PHP中解密相同的Chiphertext

How to get this work? encrypt from python and decrypt the same chiphertext in PHP

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

Note : i have to use python for encryption and php for decryption and i have to use AES-CCM, the python code is fixed , thank you for your understanding

谢谢

推荐答案

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

There seems to be a bug in the PHP implementation for AES-CCM for a nonce length of 12 bytes (used by the OP) which results in a wrong ciphertext/tag. However, this bug is hidden by a number of flaws in the OP's PHP code. Therefore, these defects have to be fixed first:


  • Python和PHP实现不同之处在于,在Python代码中密文和标记是并置的

  • Python代码中的随机数对应于PHP代码中的IV。

  • 在PHP代码中,如果密文作为原始数据而不是未经Base64编码传递,则必须设置 OPENSSL_RAW_DATA 标志。

  • 两个代码中的随机数和密文(+标记)的值不同。但是,由于选择了12个字节的随机数,再加上一个12个字节的随机数的PHP错误,因此更正是没有意义的,请参见下文。即成功测试的前提是随机数大小不等于12个字节。

  • 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.
  • The nonce in the Python code corresponds to the IV in the PHP code.
  • In the PHP code the OPENSSL_RAW_DATA flag must be set if the ciphertext is passed as raw data and not Base64 encoded.
  • The values for nonce and ciphertext (+ tag) differ in both codes. However, a correction is pointless because of the chosen 12 bytes nonce in combination with the PHP bug for a 12 bytes nonce, see below. I.e. a prerequisite for a successful test is a nonce size unequal to 12 bytes.

将这些要点考虑在内的PHP实现例如

A PHP implementation that takes these points into account is e.g.

<?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 个字节

With this PHP code it's possible to decrypt the data from the Python code as long as the length of the nonce is not equal to 12 bytes.

Python和PHP实现允许长度为 7 13的随机数个字节(包括两端),s。 此处适用于Python 。关于 12 字节随机数的问题,结果如下:如果在PHP代码中 12 字节随机数是通过删除最后的 5 个字节将其截断为 7 个字节,相同密文/标记为创建。以下PHP代码针对标记长度 8 16 字节(PHP版本7.4.4)说明了这一点: / p>

Python and PHP implementations allow a nonce with a length of 7 to 13 bytes (both inclusive), s. here for Python. Concerning the issue for a 12 bytes nonce, the following turns out: If in the PHP code the 12 bytes nonce is truncated to 7 bytes by removing the last 5 bytes, the same ciphertext/tag is created. The following PHP code illustrates this for the tag lengths of 8 and 16 bytes (PHP version 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实现中存在错误。

This result indicates a bug in the PHP implementation.

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

The Python code in contrast generates different ciphertexts/tags for a 12 bytes nonce compared to the PHP code (which is why the (corrected) OP's PHP code that uses a 12 bytes nonce fails). A check with Java/BC with identical parameters produces the same ciphertexts/tags for a 12 bytes nonce as the Python code, which verifies the values of the Python code and again indicates a bug in the PHP implementation.

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

I've filed an issue here: https://bugs.php.net/bug.php?id=79601. Note: The issue was set to private by the admins, so that it cannot be opened (at least for now) without the appropriate permissions, s. here.

这篇关于如何使用AES-256-CCM通过python在php中解密加密的文本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆