Conservation / décryptage d'une ligne avec un algorithme RSA via la bibliothèque OpenSSL indiquant les fichiers secrètes et clés publics au format PEM.
Avec une clé de 1024 bits, la longueur de la ligne à rsa_pks1_padding = 117 octets, avec RSA_NO_PADING la longueur de ligne maximale = 128 octets avec une augmentation des touches de la clé augmente la longueur de la ligne pour le cryptage.
La version actuelle est fixe et fonctionne correctement après compilation dans les versions EXE et supérieures
Implémentation du chiffrement / décryptage d'une chaîne à l'aide de l'algorithme RSA via la bibliothèque OpenSL, spécifiant les fichiers secrètes et publics au format PEM.
Avec la touche 1024 bits, la longueur de chaîne avec rsa_pks1_padding = 117 octets, avec RSA_NO_PADING , la longueur de chaîne maximale = 128 octets. L'augmentation du bit clé augmente la longueur de chaîne de chiffrement. La version actuelle a été fixée et fonctionne correctement après compilation dans les versions XE et plus
Générer une clé privée
openssl genrsa 1024 > private.pem
Générer une clé publique à partir de privé
openssl rsa -in private.pem -pubout > public.pem
Init
OpenSSL_add_all_algorithms;
OpenSSL_add_all_ciphers;
OpenSSL_add_all_digests;
ERR_load_crypto_strings;
ERR_load_RSA_strings;Détruire
EVP_cleanup;
ERR_free_strings; { Шифрование/дешифрование flen размера буфера from в буфер _to используя структуру RSA ключа загруженного ранее в режиме выравнивания
данных padding. Получаем длину шифрованного/дешифрованного буфера или -1 при ошибке
Шифрование публичным ключом }
function RSA_private_encrypt (flen: integer; from: PCharacter; _to: PCharacter; rsa: pRSA; padding: integer): integer; cdecl; { Дешифрование публичным ключом }
function RSA_public_decrypt (flen: integer; from: PCharacter; _to: PCharacter; rsa: pRSA; padding: integer): integer; cdecl; { Шифрование публичным ключом }
function RSA_public_encrypt (flen: integer; from: PCharacter; _to: PCharacter; rsa: pRSA; padding: integer): integer; cdecl; { Дешифрование секретным ключом }
function RSA_private_decrypt (flen: integer; from: PCharacter; _to: PCharacter; rsa: pRSA; padding: integer): integer; cdecl;KeyFile - Selt to the Key / Path Key ('c: key.pem'):
function LoadPublicKey (KeyFile: string) :pEVP_PKEY ;
var
mem: pBIO;
k: pEVP_PKEY;
begin
k:= nil ;
mem := BIO_new(BIO_s_file()); // BIO типа файл
BIO_read_filename(mem, PAnsiChar(KeyFile)); // чтение файла ключа в BIO
try
result := PEM_read_bio_PUBKEY(mem, k, nil , nil ); // преобразование BIO в структуру pEVP_PKEY, третий параметр указан nil, означает для ключа не нужно запрашивать пароль
finally
BIO_free_all(mem);
end ;
end ;
function LoadPrivateKey (KeyFile: string) :pEVP_PKEY;
var
mem: pBIO;
k: pEVP_PKEY;
begin
k := nil ;
mem := BIO_new(BIO_s_file());
BIO_read_filename(mem, PAnsiChar(KeyFile));
try
result := PEM_read_bio_PrivateKey(mem, k, nil , nil );
finally
BIO_free_all(mem);
end ;
end ; var
FPublicKey: pEVP_PKEY;
FPrivateKey: pEVP_PKEY;
err: Cardinal;
…
FPublicKey := LoadPublicKey(‘C: public .key’);
FPrivateKey := LoadPrivateKey(‘C: private .key’);
// if FPrivateKey = nil then // если ключ не вернулся, то читаем ошибку
if FPublicKey = nil then
begin
err := ERR_get_error;
repeat
log.Lines.Add(string(ERR_error_string(err, nil )));
err := ERR_get_error;
until err = 0 ;
end ; var
rsa: pRSA; // структура RSA
size: Integer;
FCryptedBuffer: pointer; // Выходной буфер
b64, mem: pBIO;
str, data: AnsiString;
len, b64len: Integer;
penc64: PAnsiChar;
size: Integer;
err: Cardinal
begin
rsa := EVP_PKEY_get1_RSA(FPrivateKey); // Получение RSA структуры
EVP_PKEY_free(FPrivateKey); // Освобождение pEVP_PKEY
size := RSA_size(rsa); // Получение размера ключа
GetMem(FCryptedBuffer, size); // Определение размера выходящего буфера
str := AnsiString(‘Some text to encrypt’); // Строка для шифрования
// Шифрование
len := RSA_public_encrypt(Length(str), // Размер строки для шифрования
PAnsiChar(str), // Строка шифрования
FCryptedBuffer, // Выходной буфер
rsa, // Структура ключа
RSA_PKCS1_PADDING // Определение выравнивания
);
if len > 0 then // длина буфера после шифрования
begin
// полученный бинарный буфер преобразуем в человекоподобный base64
b64 := BIO_new(BIO_f_base64); // BIO типа base64
mem := BIO_push(b64, BIO_new(BIO_s_mem)); // Stream
try
BIO_write(mem, FCryptedBuffer, len); // Запись в Stream бинарного выходного буфера
BIO_flush(mem);
b64len := BIO_get_mem_data(mem, penc64); // получаем размер строки в base64
SetLength(data, b64len); // задаем размер выходному буферу
Move(penc64^, PAnsiChar(data)^, b64len); // Перечитываем в буфер data строку в base64
finally
BIO_free_all(mem);
end ;
end
else
begin // читаем ошибку, если длина шифрованной строки -1
err := ERR_get_error;
repeat
log.Lines.Add(string(ERR_error_string(err, nil )));
err := ERR_get_error;
until err = 0 ;
end ;
RSA_free(rsa);
end ; var
rsa: pRSA;
out_: AnsiString;
str, data: PAnsiChar;
len, b64len: Integer;
penc64: PAnsiChar;
b64, mem, bio_out, bio: pBIO;
size: Integer;
err: Cardinal;
begin
// ACryptedData : string; // Строка в base64
rsa := EVP_PKEY_get1_RSA(FPublicKey);
size := RSA_size(rsa);
GetMem(data, size); // Определяем размер выходному буферу дешифрованной строки
GetMem(str, size); // Определяем размер шифрованному буферу после конвертации из base64
// Decode base64
b64 := BIO_new(BIO_f_base64);
mem := BIO_new_mem_buf(PAnsiChar(ACryptedData), Length(ACryptedData));
BIO_flush(mem);
mem := BIO_push(b64, mem);
BIO_read(mem, str , Length(ACryptedData)); // Получаем шифрованную строку в бинарном виде
BIO_free_all(mem);
// Дешифрование
len := RSA_private_decrypt(size, PAnsiChar(str), data, rsa, RSA_PKCS1_PADDING);
if len > 0 then
begin
// в буфер data данные расшифровываются с «мусором» в конца, очищаем, определяем размер переменной out_ и переписываем в нее нужное количество байт из data
SetLength(out_, len);
Move(data^, PAnsiChar(out_ )^, len);
end
else
begin // читаем ошибку, если длина шифрованной строки -1
err := ERR_get_error;
repeat
log.Lines.Add(string(ERR_error_string(err, nil )));
err := ERR_get_error;
until err = 0 ;
end ;
end ;
var
mem, keybio: pBIO;
k: pEVP_PKEY;
keystring: AnsiString;
begin
keystring :=
' -----BEGIN RSA PRIVATE KEY----- ' + # 10 +
' MIICXgIBAAKBgQCfydli2u2kJfb2WetkOekjzQIg7bIuU7AzAlBUPuA72UYXWnQ/ ' + # 10 +
' XcdSzEEMWSBLP7FO1vyVXR4Eb0/WqthF0ZViOK5bCN9CnR/1GMMiSqmIdByv/gUe ' + # 10 +
' Z/UjGrKmxeQOoa2Yt0MJC64cNXgnKmYC7ui3A12LlvNdBBEF3WpcDbv+PQIDAQAB ' + # 10 +
' AoGBAJnxukKHchSHjxthHmv9byRSyw42c0g20LcUL5g6y4Zdmi29s+moy/R1XOYs ' + # 10 +
' p/RXdNfkQI0WnWjgZScIij0Z4rSs39uh7eQ5qxK+NH3QIWeR2ZNIno9jAXPn2bkQ ' + # 10 +
' odS8FPzbZM9wHhpRvKW4FNPXqTc3ZkTcxi4zOwOdlECf9G+BAkEAzsJHgW1Isyac ' + # 10 +
' I61MDu2qjMUwOdOBYS8GwEBfi/vbn/duwZIBXG/BZ7Pn+cBwImfksEXwx0MTkgF3 ' + # 10 +
' gyaChUSu+QJBAMXX3d94TwcF7lG9zkzc+AR/Onl4Z5UAb1GmUV57oYIFVgW1RIOk ' + # 10 +
' vqynXWrTjTOg9C9j+VEpBG67LcnkwU16JmUCQH7pukKz9kAhnw43PcycDmhCUgvs ' + # 10 +
' zCn/V8GCwiOHAZT7qLyhBrzazHj/cZFYknxMEZAyHk3x2n1w8Q9MACoVsuECQQDF ' + # 10 +
' U7cyara31IyM7vlS5JpjMdrKyPLXRKXDFFXYHQtLubLA4rlBbBHZ9txP7kzJj+G9 ' + # 10 +
' WsOS1YxcPUlAM28xrYGZAkEArVKJHX4dF8UUtfvyv78muXJZNXTwmaaFy02xjtR5 ' + # 10 +
' uXWT1QjVN2a6jv6AW7ukXiSoE/spgfvdoriMk2JSs88nUw== ' + # 10 +
' -----END RSA PRIVATE KEY----- ' ;
k := nil ;
keybio := BIO_new_mem_buf(Pchar(keystring), - 1 );
mem := BIO_new(BIO_s_mem());
BIO_read(mem, PAnsiChar(keystring), length(PAnsiChar(keystring)));
try
result := PEM_read_bio_PrivateKey(keybio, k, nil , nil );
finally
BIO_free_all(mem);
end ;
end ;