为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
米琪卡哇伊 2023-03-11 16:48:51
AES-256-CCM我正在尝试解密使用Python加密的 PHP 密文,cryptography.hazmat我在 Python 代码中所做的是:from cryptography.hazmat.primitives.ciphers.aead import AESCCMfrom os import urandomimport base64#Text To Encryptplaintext = bytes("message from python", encoding='utf-8')#AES 256 Key Genratorkey = AESCCM.generate_key(256)#Genrate Noncenonce= urandom(12)#chipher cipher = AESCCM(key, tag_length=8)#Encryptionciphertext = cipher.encrypt(nonce, plaintext, None)key然后我将,nonce和转换ciphertext为 base64key_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\x9dnonce_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我找不到另一个例子,解密过程没有返回任何东西,真正让我困惑的是:我们没有使用 IV 在 python 代码中加密,但是 PHP 需要非 NULL IV,如何解决?PHP 代码中的什么$tag以及 PHP 和 python 中的 $tag_lenght(cipher = AESCCM(key, tag_length=8)) ?如果解密需要nonce如何在我的 PHP 代码中使用它?如何获得这份工作?从 python 加密并在 PHP 中解密相同的密文注意:我必须使用 python 进行加密,使用 php 进行解密,我必须使用 AES-CCM,python 代码是固定的,谢谢您的理解
查看完整描述

1 回答

?
PIPIONE

TA贡献1829条经验 获得超9个赞

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

  • Python 和 PHP 实现的不同之处在于,在 Python 代码中,密文和标签按此顺序连接,而在 PHP 代码中,密文和标签是分开处理的。

  • Python 代码中的 nonce 对应于 PHP 代码中的 IV。

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

  • nonce 和 ciphertext (+ tag) 的值在两个代码中不同。然而,由于选择的 12 字节随机数与 12 字节随机数的 PHP 错误相结合,更正毫无意义,请参见下文。即,成功测试的先决条件是随机数大小不等于 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 的长度不等于12bytes,就可以从 Python 代码解密数据。


Python 和 PHP 实现允许长度为7to13字节(包括两者),s 的随机数。这里是 Python。关于字节 nonce 的问题12,结果如下:如果在 PHP 代码中通过删除最后一个字节12将字节 nonce 截断为字节,则会创建相同的密文/标签。以下 PHP 代码针对和字节的标记长度说明了这一点(PHP 版本 7.4.4):75816


<?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字节随机数生成不同的密文/标签(这就是为什么(更正的)OP 的使用字节12随机数的 PHP 代码失败的原因)。使用具有相同参数的 Java/BC 进行的检查会为字节随机数生成与 Python 代码相同的密文/标签,从而验证 Python 代码的值并再次指示 PHP 实现中的错误。12



查看完整回答
反对 回复 2023-03-11
  • 1 回答
  • 0 关注
  • 218 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信