Почему результаты AES-256-CBC в PHP и Python различаются при использовании одних и тех же ключей и данных?

Я пытаюсь зашифровать одну и ту же строку в 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)

Я проверил следующее:

  • Ключи и IV на обоих языках генерируются одинаково с использованием SHA-256.
  • Я использую режим CBC и применяю дополнение PKCS7 на обоих языках.
  • Оба результата закодированы в Base64.

Несмотря на эти шаги, результаты остаются разными. Я не уверен, почему это происходит.

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
2
0
50
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Функция 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.

Проще просто передать true в качестве третьего параметра hash().

Olivier 05.09.2024 18:23

Спасибо, Оливье. Я давно не использовал PHP! Должен ли я отредактировать свой ответ или вы хотите оказать мне честь?

mmdts 05.09.2024 18:24

Просто отредактируйте свой ответ.

Olivier 05.09.2024 18:25

Оливье и ммдтс спасибо! не могли бы вы взглянуть на другой пример, который я только что прокомментировал? в этом сценарии тоже не работает, хотя iv и ключ одинаковы.

Yeivicr 05.09.2024 18:43

@Yeinor Я бы задал еще один вопрос, потому что он слишком отличается.

Olivier 05.09.2024 18:50

Другие вопросы по теме

Похожие вопросы