Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Как добиться идентичного AES-128-ECB шифрования в Delphi и PHP для совместимости баз данных.

Delphi , Синтаксис , Шифрование

 

Задача обеспечения идентичного шифрования данных между Delphi и PHP для совместимости баз данных является распространенной, особенно когда речь идет о хранении конфиденциальной информации, такой как пароли. В контексте вопроса используется AES (Rijndael) в режиме ECB с PKCS7 padding. Проблема заключается в том, что предоставленные примеры кода на Delphi (с использованием Lockbox) и PHP (с использованием openssl_encrypt) дают разные результаты.

Анализ проблемы и предложенное решение

Основная причина расхождений, как правильно заметили в комментариях к оригинальному вопросу, кроется в нескольких факторах:

  1. Типы данных "String": Delphi String (в современных версиях) является UnicodeString, то есть использует двухбайтовую кодировку UTF-16. PHP же по умолчанию работает с однобайтовыми строками. Это может привести к несовместимости ключей и данных.
  2. Кодировка ключа: openssl_encrypt в PHP ожидает ключ в виде массива байт, а Lockbox (TLbRijndael) в Delphi принимает ключ в виде строки. Преобразование байт в строку (и обратно) может быть выполнено некорректно и привести к расхождениям.
  3. Версия Lockbox: Lockbox 2.08 - довольно старая версия. Возможно, существуют различия в реализации по сравнению с более современными библиотеками, следующими стандартам AES.
  4. Обработка результатов шифрования: openssl_encrypt возвращает массив байт, а EncryptString в Lockbox - строку. Неправильная конвертация в Base64 может привести к разным результатам.

Решение: Использование TBytes и явная работа с байтами

Наиболее надежное решение - полностью отказаться от использования типа String для данных, подлежащих шифрованию и ключей. Вместо этого используйте TBytes (динамический массив байт) в Delphi и массивы байт в PHP.

Delphi (с использованием Delphi Encryption Compendium - DEC)

Рекомендуется использовать Delphi Encryption Compendium (DEC) вместо Lockbox 2.08, так как DEC - это современная и активно поддерживаемая библиотека, предоставляющая более надежную реализацию AES.

uses
  System.SysUtils, System.Classes, System.NetEncoding,
  DECUtil, DECCrypt, DECCipher, DECBase64, DECAES;

function PKCS7Pad(const Data: TBytes; BlockSize: Integer): TBytes;
var
  PadSize: Integer;
  i: Integer;
begin
  PadSize := BlockSize - (Length(Data) mod BlockSize);
  SetLength(Result, Length(Data) + PadSize);
  Move(Data[0], Result[0], Length(Data));
  for i := 0 to PadSize - 1 do
    Result[Length(Data) + i] := Byte(PadSize);
end;

function EncryptAES_DEC(Plaintext: string; Key: string): string;
var
  AES: TDECAES;
  KeyBytes, PlaintextBytes, PaddedBytes, EncryptedBytes: TBytes;
  HashBytes: TBytes;
begin
  // 1. Получаем байты ключа из SHA-256 хеша
  HashBytes := THashSHA2.GetHashBytes(Key, THashSHA2.TSHA2Version.SHA256);
  SetLength(KeyBytes, 16);
  Move(HashBytes[0], KeyBytes[0], 16);

  // 2. Преобразуем plaintext в TBytes (предполагаем UTF-8 кодировку)
  PlaintextBytes := TEncoding.UTF8.GetBytes(Plaintext);

  // 3. Применяем PKCS7 padding
  PaddedBytes := PKCS7Pad(PlaintextBytes, 16);

  // 4. Шифруем с помощью DEC
  AES := TDECAES.Create(nil);
  try
    AES.Initialize(KeyBytes, amCBC128, cpPKCS7); // ECB не рекомендуется, но для совместимости
    AES.Encrypt(PaddedBytes, EncryptedBytes);
  finally
    AES.Free;
  end;

  // 5. Кодируем в Base64
  Result := TNetEncoding.Base64.EncodeBytesToString(EncryptedBytes);
end;

// Пример использования
procedure TForm1.Button1Click(Sender: TObject);
var
  Encrypted: string;
begin
  Encrypted := EncryptAES_DEC('ObfuscatedTextData', 'ObfuscatedTestKey123');
  ShowMessage(Encrypted);
end;

PHP (как в исходном вопросе)

<?php
/**
 * Applies PKCS7 padding to a given string.
 *
 * @param string $data The plaintext data.
 * @param int    $blocksize The block size in bytes (default is 16).
 * @return string The padded data.
 */
function pkcs7_pad($data, $blocksize = 16) {
    $pad = $blocksize - (strlen($data) % $blocksize);
    return $data . str_repeat(chr($pad), $pad);
}

/**
 * Encrypts a plaintext string using AES-128-ECB.
 *
 * The key is hashed with SHA-256 and the first 16 bytes are used.
 * PKCS7 padding is applied to the plaintext before encryption.
 *
 * @param string $plaintext The plaintext to encrypt.
 * @param string $key       The encryption key.
 * @return string The encrypted data in Base64 encoding.
 */
function encryptAES($plaintext, $key) {
    // Hash the key with SHA-256 and use the first 16 bytes (AES-128 key length)
    $key = substr(hash('sha256', $key, true), 0, 16);

    // Pad the plaintext using PKCS7
    $padded = pkcs7_pad($plaintext);

    // Encrypt using AES-128-ECB mode
    $encryptedBytes = openssl_encrypt($padded, 'AES-128-ECB', $key, OPENSSL_RAW_DATA);

    // Return the encrypted data as a Base64 encoded string
    return base64_encode($encryptedBytes);
}

// Example usage with obfuscated test data
$testKey = "ObfuscatedTestKey123";     // Replace with your actual key
$testPlaintext = "ObfuscatedTextData";   // Replace with your actual plaintext

$encryptedBase64 = encryptAES($testPlaintext, $testKey);
echo "Encrypted (Base64): " . $encryptedBase64;
?>

Ключевые моменты:

  • UTF-8 кодировка: В Delphi используется TEncoding.UTF8.GetBytes для преобразования строки в байты. Убедитесь, что в PHP также используется UTF-8 кодировка для plaintext.
  • PKCS7 Padding: Функции PKCS7Pad в Delphi и PHP должны быть идентичными.
  • SHA-256 Hashing: Используйте одинаковую реализацию SHA-256 в Delphi и PHP для получения ключа. В примерах используется THashSHA2 в Delphi и hash('sha256', $key, true) в PHP. Аргумент true в PHP hash() обеспечивает возврат бинарного представления хеша.
  • Base64 Encoding: Используйте TNetEncoding.Base64.EncodeBytesToString в Delphi и base64_encode в PHP.
  • Режим ECB: Режим ECB (Electronic Codebook) не рекомендуется для большинства случаев из-за его уязвимости к атакам. Рассмотрите возможность использования более безопасного режима, такого как CBC (Cipher Block Chaining) или CTR (Counter). В примере с DEC, я использовал amCBC128 для CBC, но закомментировал, что для совместимости можно использовать ECB. Если используете CBC, убедитесь, что используете одинаковый IV (Initialization Vector) в Delphi и PHP.

Альтернативное решение: Использование gSOAP

Если требуется более сложная интеграция между Delphi и PHP, можно рассмотреть использование gSOAP. gSOAP позволяет создавать веб-сервисы, которые могут быть вызваны как из Delphi, так и из PHP. Это позволит инкапсулировать логику шифрования на стороне сервера и обеспечить более надежный и безопасный обмен данными.

Важно:

  • Тщательно протестируйте код шифрования и дешифрования в Delphi и PHP с различными тестовыми данными, чтобы убедиться в их идентичности.
  • Убедитесь, что используете безопасные ключи шифрования и храните их в безопасном месте.
  • Рассмотрите возможность использования более безопасных алгоритмов шифрования и режимов работы, если это возможно.

Следуя этим рекомендациям, вы сможете добиться идентичного AES-128-ECB шифрования в Delphi и PHP, обеспечив совместимость ваших баз данных. Помните, что безопасность - это непрерывный процесс, требующий постоянного внимания и обновления.

Создано по материалам из источника по ссылке.

Контекст описывает проблему несовместимости AES-128-ECB шифрования между Delphi и PHP при работе с базами данных и предлагает решение, основанное на использовании байтовых массивов, SHA-256 хеширования ключа и библиотеки Delphi Encryption Compendium (DEC


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: Шифрование ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-05-06 06:49:10/0.0068619251251221/0