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

Ошибка "Invalid key material" при работе с шифрованием AES256GCM в Delphi

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

 

В процессе работы с библиотекой SecureBlackBox для шифрования и расшифровки данных вы столкнулись с ошибкой "Invalid key material". Это означает, что ключ, который вы используете для расшифровки данных, некорректен. В этой статье мы рассмотрим возможные причины этой ошибки и предложим решения для её устранения.

Описание проблемы

В вашем коде используется библиотека SecureBlackBox для расшифровки данных, зашифрованных с использованием алгоритма AES256GCM. При попытке расшифровать данные вы получаете ошибку "Invalid key material". Это может быть вызвано несколькими причинами:

  1. Некорректный ключ: Ключ, который вы используете для расшифровки, может быть неправильным или некорректным.
  2. Некорректный вектор инициализации (IV): Вектор инициализации также должен быть правильным и совпадать с тем, который использовался при шифровании.
  3. Неправильное преобразование данных: Возможно, данные, которые вы передаете для расшифровки, не были правильно преобразованы из строкового представления в байтовый массив.

Анализ кода

Давайте разберем ваш код и попробуем найти возможные проблемы:

function DecryptAES256GCM(aData, aSal, aKey: String): string;

  function Base64UrlDecode(Input: string): TBytes;
  begin
    Result := TNetEncoding.Base64.DecodeStringToBytes(
      StringReplace(
        StringReplace(Input, '-', '+', [rfReplaceAll]),
        '_', '/', [rfReplaceAll]
      )
    );
  end;

var
  Crypto : TElSymmetricCrypto;
  KeyMaterial : TElSymmetricKeyMaterial;
  Factory : TElSymmetricCryptoFactory;
  fIV, fKey, fDataBin, fDataBytes, fDecryptedData : TBytes;
  OutSize : integer;
  Data: RawByteString;
  KeyBinary, IVBinary : ByteArray;
begin
  //Definice
  result := '';

  //Převedení vstupních dat
  fDataBin    := Base64UrlDecode(aData);
  fIV         := Base64UrlDecode(aSal);
  fKey        := Base64UrlDecode(aKey);

  //Přehodit IV - Salt
  SetLength(IVBinary, Length(fIV) * SizeOf(Char));
  Move(Pointer(fIV)^, IVBinary[0], Length(IVBinary));

  //Přehodit Key
  SetLength(KeyBinary, Length(fKey) * SizeOf(Char));
  Move(Pointer(fKey)^, KeyBinary[0], Length(KeyBinary));

  //Přehodit data
  SetLength(fDataBytes, Length(fDataBin));
  Move(fDataBin[0], fDataBytes[0], Length(fDataBytes));

  // Inicializace objektů SecureBlackBox
  Factory := TElSymmetricCryptoFactory.Create;
  Crypto  := Factory.CreateInstance(SB_ALGORITHM_CNT_AES256, cmGCM);  // <-- Error
  try
    KeyMaterial     := TElSymmetricKeyMaterial.Create;
    KeyMaterial.Key := KeyBinary;
    KeyMaterial.IV  := IVBinary;
    Crypto.Padding  := cpNone;

    Crypto.KeyMaterial := KeyMaterial;
    try
      //Dešifrování -- délka
      OutSize := 0;
      Crypto.Decrypt(@fDataBytes[0], Length(fDataBytes), nil, OutSize);
      if OutSize < 0 then
        raise Exception.Create('Failed to decrypt data');

      //Komplet
      SetLength(fDecryptedData, OutSize);
      Crypto.Decrypt(@fDataBytes[0], Length(fDataBytes), @fDecryptedData[0], OutSize);
      if OutSize < 0 then
        raise Exception.Create('Failed to decrypt data');

      SetLength(fDecryptedData, OutSize);

      // Výstup do řetězce
      result := TEncoding.UTF8.GetString(fDecryptedData);
    except
      on E: Exception do
        ShowMessage(E.Message);
    end;
  finally
    Factory.Free;
    Crypto.Free;
    KeyMaterial.Free;
  end;
end;

Возможные проблемы и их решение

  1. Некорректное преобразование ключа и IV:
    В вашем коде вы используете Length(fIV) * SizeOf(Char) для выделения памяти под IVBinary. Это может быть некорректным, если ваша строка fIV содержит символы, требующие больше одного байта для хранения (например, широкие символы). Вместо этого вы должны использовать Length(fIV) * SizeOf(Byte), чтобы выделить правильное количество байтов.
  2. Некорректное преобразование данных:
    Вы также используете Length(fDataBin) * SizeOf(Char) для выделения памяти под fDataBytes. Это также может быть некорректным. Вместо этого вы должны использовать Length(fDataBin) * SizeOf(Byte).

  3. Некорректный ключ:
    Убедитесь, что ваш ключ aKey действительно является правильным ключом для расшифровки данных. Ключ должен быть 32 байта для AES256.

  4. Некорректный вектор инициализации (IV):
    Убедитесь, что ваш вектор инициализации aSal действительно является правильным вектором инициализации. Вектор инициализации должен быть 12 байт для AES256GCM.

Исправленный код

Давайте исправим ваш код, устранив указанные проблемы:

function DecryptAES256GCM(aData, aSal, aKey: String): string;

  function Base64UrlDecode(Input: string): TBytes;
  begin
    Result := TNetEncoding.Base64.DecodeStringToBytes(
      StringReplace(
        StringReplace(Input, '-', '+', [rfReplaceAll]),
        '_', '/', [rfReplaceAll]
      )
    );
  end;

var
  Crypto : TElSymmetricCrypto;
  KeyMaterial : TElSymmetricKeyMaterial;
  Factory : TElSymmetricCryptoFactory;
  fIV, fKey, fDataBin, fDataBytes, fDecryptedData : TBytes;
  OutSize : integer;
  Data: RawByteString;
  KeyBinary, IVBinary : ByteArray;
begin
  //Definice
  result := '';

  //Převedení vstupních dat
  fDataBin    := Base64UrlDecode(aData);
  fIV         := Base64UrlDecode(aSal);
  fKey        := Base64UrlDecode(aKey);

  //Přehodit IV - Salt
  SetLength(IVBinary, Length(fIV) * SizeOf(Byte));
  Move(Pointer(fIV)^, IVBinary[0], Length(IVBinary));

  //Přehodit Key
  SetLength(KeyBinary, Length(fKey) * SizeOf(Byte));
  Move(Pointer(fKey)^, KeyBinary[0], Length(KeyBinary));

  //Přehodit data
  SetLength(fDataBytes, Length(fDataBin) * SizeOf(Byte));
  Move(fDataBin[0], fDataBytes[0], Length(fDataBytes));

  // Inicializace objektů SecureBlackBox
  Factory := TElSymmetricCryptoFactory.Create;
  Crypto  := Factory.CreateInstance(SB_ALGORITHM_CNT_AES256, cmGCM);  // <-- Error
  try
    KeyMaterial     := TElSymmetricKeyMaterial.Create;
    KeyMaterial.Key := KeyBinary;
    KeyMaterial.IV  := IVBinary;
    Crypto.Padding  := cpNone;

    Crypto.KeyMaterial := KeyMaterial;
    try
      //Dešifrování -- délka
      OutSize := 0;
      Crypto.Decrypt(@fDataBytes[0], Length(fDataBytes), nil, OutSize);
      if OutSize < 0 then
        raise Exception.Create('Failed to decrypt data');

      //Komplet
      SetLength(fDecryptedData, OutSize);
      Crypto.Decrypt(@fDataBytes[0], Length(fDataBytes), @fDecryptedData[0], OutSize);
      if OutSize < 0 then
        raise Exception.Create('Failed to decrypt data');

      SetLength(fDecryptedData, OutSize);

      // Výstup do řetězce
      result := TEncoding.UTF8.GetString(fDecryptedData);
    except
      on E: Exception do
        ShowMessage(E.Message);
    end;
  finally
    Factory.Free;
    Crypto.Free;
    KeyMaterial.Free;
  end;
end;

Альтернативное решение

Если вы все еще сталкиваетесь с проблемой, вы можете попробовать использовать другой подход для расшифровки данных. Например, вы можете использовать библиотеку OpenSSL для расшифровки данных. Вот пример кода на Object Pascal, который использует OpenSSL для расшифровки данных:

uses
  OpenSSL;

function DecryptAES256GCM_OpenSSL(aData, aSal, aKey: String): string;
var
  bioData, bioIV, bioKey: PBIO;
  cipher: PEVP_CIPHER;
  ctx: PEVP_CIPHER_CTX;
  outLen: Cardinal;
  outData: array of Byte;
begin
  // Initialize OpenSSL
  OpenSSL_add_all_algorithms;
  OpenSSL_add_all_ciphers;

  // Create BIO objects for data, IV, and key
  bioData := BIO_new_mem_buf(PChar(aData), Length(aData));
  bioIV := BIO_new_mem_buf(PChar(aSal), Length(aSal));
  bioKey := BIO_new_mem_buf(PChar(aKey), Length(aKey));

  // Create cipher context
  ctx := EVP_CIPHER_CTX_new;

  // Set up cipher
  cipher := EVP_aes_256_gcm;
  EVP_DecryptInit_ex(ctx, cipher, nil, nil, nil);

  // Set key and IV
  EVP_DecryptInit_ex(ctx, nil, nil, bioKey, bioIV);

  // Allocate memory for output data
  SetLength(outData, Length(aData) + EVP_CIPHER_block_size(cipher));

  // Perform decryption
  outLen := 0;
  EVP_DecryptUpdate(ctx, Pointer(outData)^, @outLen, bioData, Length(aData));
  EVP_DecryptFinal_ex(ctx, Pointer(outData)^ + outLen, @outLen);

  // Clean up
  EVP_CIPHER_CTX_free(ctx);
  BIO_free_all(bioData);
  BIO_free_all(bioIV);
  BIO_free_all(bioKey);

  // Convert output data to string
  result := TEncoding.UTF8.GetString(outData);
end;

Этот код использует библиотеку OpenSSL для расшифровки данных с использованием алгоритма AES256GCM. Он создает объекты BIO для данных, IV и ключа, инициализирует контекст шифрования и выполняет расшифровку данных.

Заключение

Ошибка "Invalid key material" может быть вызвана несколькими причинами, включая некорректный ключ, некорректный вектор инициализации или неправильное преобразование данных. В этой статье мы рассмотрели возможные причины этой ошибки и предложили решения для её устранения. Если вы все еще сталкиваетесь с проблемой, вы можете попробовать использовать другой подход для расшифровки данных, например, библиотеку OpenSSL.

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

В статье рассматривается ошибка "Invalid key material" при использовании библиотеки SecureBlackBox для расшифровки данных, предлагаются возможные причины и способы их устранения, включая исправление кода и альтернативное решение с использованием OpenSSL.


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

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




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


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


реклама


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

Время компиляции файла: 2024-12-22 20:14:06
2025-06-16 10:54:59/0.0064198970794678/0