gpt4 book ai didi

php - 在 PHP 中加密文本并在 Python 中解密

转载 作者:行者123 更新时间:2023-11-28 22:13:09 25 4
gpt4 key购买 nike

我正在使用以下代码片段来加密 PHP7 中的文本:

$plaintext = "message to be encrypted";
$cipher = "aes-256-cbc";
$ivlen = openssl_cipher_iv_length($cipher);
$iv = "0123456789012345";
$key = "akshayakshayaksh";
$ciphertext = openssl_encrypt($plaintext, $cipher, $key, $options=0, $iv);
print $ciphertext;

Output: cUXDhOEGz19QEo9XDvMzXkGFmg/YQUnXEqKVpfYtUGo=

现在,当我尝试在 Python3 中解密时,出现错误:

from Crypto.Cipher import AES
obj2 = AES.new('akshayakshayaksh', AES.MODE_CBC, '0123456789012345')
ciphertext = "cUXDhOEGz19QEo9XDvMzXkGFmg/YQUnXEqKVpfYtUGo="
obj2.decrypt(ciphertext)

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/anaconda3/lib/python3.6/site-packages/Crypto/Cipher/blockalgo.py", line 295, in decrypt return self._cipher.decrypt(ciphertext) ValueError: Input strings must be a multiple of 16 in length

我知道 AES 是一种分组密码算法。但是,我应该如何修复我的 PHP 代码,以便它生成“填充”密码,有什么线索吗?

最佳答案

这里的主要问题是您使用了不同的 key 大小。 PHP 的 openssl_encrypt 从加密算法字符串(在本例中为 "aes-256-cbc")确定 key 大小,因此它需要一个 256 位 key 。如果 key 较短,则用零字节填充,因此 openssl_encrypt 使用的实际 key 是:

"akshayakshayaksh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

Pycryptodome 根据 key 的实际大小确定 key 大小,因此您的 Python 代码使用 AES-128-CBC。此外,正如 kelalaka 在 coments 中提到的,密文是 base64 编码的( openssl_encrypt base64-默认情况下对密文进行编码 - 如果我们在 OPENSSL_RAW_DATA 中使用 $options ,我们可以获得原始字节)。 Pycryptodome 不解码密文,所以我们必须使用 b64decode()

key = b'akshayakshayaksh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
obj2 = AES.new(key, AES.MODE_CBC, b'0123456789012345')
ciphertext = b"cUXDhOEGz19QEo9XDvMzXkGFmg/YQUnXEqKVpfYtUGo="
print(obj2.decrypt(b64decode(ciphertext)))
#b'message to be encrypted\t\t\t\t\t\t\t\t\t'

最后的额外 \t 字符是填充 - CBC 需要填充。 Pycryptodome 不会自动删除填充,但它在 Crypto.Util.Padding 中提供了填充函数。

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
from base64 import b64decode

key = b'akshayakshayaksh\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'
obj2 = AES.new(key, AES.MODE_CBC, b'0123456789012345')
ciphertext = b"cUXDhOEGz19QEo9XDvMzXkGFmg/YQUnXEqKVpfYtUGo="
plaintext = obj2.decrypt(b64decode(ciphertext))
plaintext = unpad(plaintext, AES.block_size)

虽然 PHP 的 openssl 接受任意大小的 key ,但最好使用在算法字符串中指定的 key 大小,至少可以防止混淆。此外, key 字节应尽可能随机。

正如 Maarten Bodewes 在 comments 中指出的那样,此 key 使用的字节范围有限,因此非常脆弱。此外,它是通过重复一个词创建的,这使得它容易受到字典攻击(比暴力攻击快得多)。

在 PHP 中,我们可以使用 random_bytes() 获得加密安全的随机字节,

$key = random_bytes(32);  

在 Python 中使用 os.urandom()

key = os.urandom(32)

(您可以使用相同的函数来创建 IV;您不应该使用静态 IV,IV 必须是不可预测的)

您还可以使用 KDF 从您的密码中导出 key 。在这种情况下,重要的是使用随机盐和足够多的迭代次数。 PHP 提供了一个带有 hash_pbkdf2 函数的 PBKDF2 算法,Python 提供了一个带有 hashlib.pbkdf2_hmac 的算法。

关于php - 在 PHP 中加密文本并在 Python 中解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54176838/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com