В процессе работы с библиотекой SecureBlackBox для шифрования и расшифровки данных вы столкнулись с ошибкой "Invalid key material". Это означает, что ключ, который вы используете для расшифровки данных, некорректен. В этой статье мы рассмотрим возможные причины этой ошибки и предложим решения для её устранения.
Описание проблемы
В вашем коде используется библиотека SecureBlackBox для расшифровки данных, зашифрованных с использованием алгоритма AES256GCM. При попытке расшифровать данные вы получаете ошибку "Invalid key material". Это может быть вызвано несколькими причинами:
Некорректный ключ: Ключ, который вы используете для расшифровки, может быть неправильным или некорректным.
Некорректный вектор инициализации (IV): Вектор инициализации также должен быть правильным и совпадать с тем, который использовался при шифровании.
Неправильное преобразование данных: Возможно, данные, которые вы передаете для расшифровки, не были правильно преобразованы из строкового представления в байтовый массив.
Анализ кода
Давайте разберем ваш код и попробуем найти возможные проблемы:
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;
Возможные проблемы и их решение
Некорректное преобразование ключа и IV:
В вашем коде вы используете Length(fIV) * SizeOf(Char) для выделения памяти под IVBinary. Это может быть некорректным, если ваша строка fIV содержит символы, требующие больше одного байта для хранения (например, широкие символы). Вместо этого вы должны использовать Length(fIV) * SizeOf(Byte), чтобы выделить правильное количество байтов.
Некорректное преобразование данных:
Вы также используете Length(fDataBin) * SizeOf(Char) для выделения памяти под fDataBytes. Это также может быть некорректным. Вместо этого вы должны использовать Length(fDataBin) * SizeOf(Byte).
Некорректный ключ:
Убедитесь, что ваш ключ aKey действительно является правильным ключом для расшифровки данных. Ключ должен быть 32 байта для AES256.
Некорректный вектор инициализации (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
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.