Я пытаюсь зашифровать одну и ту же строку в PHP и Python, используя AES-256-CBC, с теми же ключами и IV. Однако результаты обоих языков разные, хотя я использую один и тот же метод шифрования и одни и те же данные.
В PHP я использую openssl_encrypt
, а в Python — pycryptodome
с дополнением PKCS7. Ниже приведены два фрагмента кода, которые я использую, и результаты, которые я получаю.
Вот мой PHP-код:
<?php
$plaintextstr = 'AAAAAAAAAAAAAAAA';
$encrypt_method = "AES-256-CBC";
$secret_key = "SSSSSSSSSSSS";
$secret_iv = "LLLLLLLLLLLL";
$key = substr(hash('sha256', $secret_key), 0, 32);
$iv = substr(hash('sha256', $secret_iv), 0, 16);
$encrypted_str = openssl_encrypt($plaintextstr, $encrypt_method, $key, 0, $iv);
echo base64_encode($encrypted_str);
?>
Вот мой код Python:
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
from hashlib import sha256
import base64
plaintextstr = 'AAAAAAAAAAAAAAAA'
secret_key = "SSSSSSSSSSSS"
secret_iv = "LLLLLLLLLLLL"
# Generar key y iv
key = sha256(secret_key.encode('utf-8')).digest()[:32]
iv = sha256(secret_iv.encode('utf-8')).digest()[:16]
# Padding
padded_data = pad(plaintextstr.encode('utf-8'), AES.block_size)
# Crear el cifrador
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(padded_data)
# Convertir a base64
encrypted_base64 = base64.b64encode(encrypted).decode('utf-8')
print(encrypted_base64)
Я проверил следующее:
Несмотря на эти шаги, результаты остаются разными. Я не уверен, почему это происходит.
🤔 А знаете ли вы, что...
Python популярен в анализе данных и машинном обучении с помощью библиотеки scikit-learn.
Функция php hash возвращает шестнадцатеричное представление байтов, поэтому сокращение 16 символов с помощью substr приводит к «20139ebeee312271» для вашего IV (аналогичный результат для ключа). Это не настоящие байты, это символы диапазона [0-9a-f]
. Это не то, что вы собираетесь делать.
Функция Python sha256
.digest() возвращает байтовую строку, а не шестнадцатеричное представление. Вырезание 16 символов приводит к получению 16 истинных байтов хеша. Вероятно, это то, что вы намереваетесь сделать.
Результаты будут разными, поскольку вы шифруете разными ключами и векторами инициализации.
Из документации PHP hash
может принимать третий параметр binary
, который по умолчанию имеет значение false:
hash( string $algo, string $data, bool $binary = false, array $options = [] ): string
binary
Если установлено значение true, выводятся необработанные двоичные данные. false выводит шестнадцатеричные строчные буквы.
Изменение PHP-кода на:
<?php
$plaintextstr = 'AAAAAAAAAAAAAAAA';
$encrypt_method = "AES-256-CBC";
$secret_key = "SSSSSSSSSSSS";
$secret_iv = "LLLLLLLLLLLL";
$key = substr(hash('sha256', $secret_key, true), 0, 32);
$iv = substr(hash('sha256', $secret_iv, true), 0, 16);
$encrypted_str = openssl_encrypt($plaintextstr, $encrypt_method, $key, 0, $iv);
echo $encrypted_str;
// Result: V7zSp9KHPke9QuPbWoUNvjCHVJ7giluD9YaOnX9E57k=
дает тот же результат, что и код Python.