【问题标题】:how to decrypt in php an encrypted text by python using AES-256-CCM如何使用 AES-256-CCM 在 php 中通过 python 解密加密文本
【发布时间】:2020-05-13 18:18:45
【问题描述】:

我试图在 PHP 中解密一个用 AES-256-CCM 在 python 中使用 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代码是固定的,谢谢你的理解

谢谢

【问题讨论】:

  • 您的 PHP 代码充满了如此多的错误,并且您的大量数据被错误转录或完全损坏,以至于无法为您提供任何有用的信息。我可以肯定地说的一件事是,您需要在 PHP 中打开错误报告,这样您才能看到代码生成的错误页面。
  • 如果我在 PHP 中完成所有操作,解密和加密工作正常,但如果我尝试解密用 python 加密的内容,以及关于数据我将所有内容转换为 base64 以不丢失数据,它就不起作用,是的,错误报告已打开,并且没有错误报告,你能告诉我 php 中的错误是什么,至少是专业的错误
  • 那么您运行的 PHP 肯定与您发布的完全不同。我敢打赌python中的nonce是PHP中的iv。如果您想查看错误,只需复制/粘贴您发布的 PHP 并尝试运行它。变量被使用但未初始化,变量名称中的拼写错误,密文和随机数被完全错误转录,即使在修复 后密文长度不正确。
  • 如果你很好地阅读了我的问题,你就会明白我在寻找什么,问题是,在 python 中我们有 nonce key ciphertext 但在 PHP 中它需要 $tag$IV $ciphertext 和可选的 $tag_length ,如果 nonce 被错误转录,你能给我一个更好的方法在 PHP 中重用,它给你错误的问题是因为它需要 $tag这就是为什么我首先问这个问题的原因,它代表什么标签,如果你把IV 写成nonce 那么tag 是什么,如果你把tag 写成nonce 我们要做什么IV 怎么办?

标签: python php cryptography aes


【解决方案1】:

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

  • Python 和 PHP 实现的不同之处在于,在 Python 代码中,密文和标签按顺序连接,而在 PHP 代码中,密文和标签是分开处理的。
  • Python 代码中的 nonce 对应 PHP 代码中的 IV。
  • 如果密文作为原始数据而不是 Base64 编码传递,则必须在 PHP 代码中设置 OPENSSL_RAW_DATA 标志。
  • nonce 和密文(+ 标记)的值在两种代码中不同。但是,由于选择的 12 字节 nonce 以及针对 12 字节 nonce 的 PHP 错误,更正是没有意义的,见下文。 IE。成功测试的先决条件是 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 代码,可以从 Python 代码中解密数据只要 nonce 的长度不等于 12 字节

Python 和 PHP 实现允许使用长度为 713 字节(包括两者)的随机数,s。 here for Python。关于12 字节随机数的问题,结果如下:如果在 PHP 代码中,12 字节随机数通过删除最后一个 5 字节被截断为7 字节,相同 em> 密文/标签被创建。以下 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 字节随机数的(更正的)OP 的 PHP 代码失败的原因)。使用相同参数对 Java/BC 进行检查会为 12 字节 nonce 生成 same 密文/标签作为 Python 代码,这会验证 Python 代码的值并再次指示 PHP 中的错误实施。

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

【讨论】:

    猜你喜欢
    • 2012-05-10
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-23
    相关资源
    最近更新 更多