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

AES-256-CCM我正在尝试解密使用Python加密的 PHP 密文,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)

key然后我将,nonce和转换ciphertext为 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. 我们没有使用 IV 在 python 代码中加密,但是 PHP 需要非 NULL IV,如何解决?

  2. PHP 代码中的什么$tag以及 PHP 和 python 中的 $tag_lenght(cipher = AESCCM(key, tag_length=8)) ?

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

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

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


米琪卡哇伊
浏览 219回答 1
1回答

PIPIONE

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);// Decryptif (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<?phpfunction 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
打开App,查看更多内容
随时随地看视频慕课网APP