RSA via OpenSSL libeay32
Delphi XE Builded
PEM 형식의 비밀 및 공개 키 파일을 나타내는 OpenSSL 라이브러리를 통한 RSA 알고리즘이있는 라인의 보존/암호화.
1024 비트의 키를 사용하면 RSA_PKS1_PADDING = 117 바이트의 선 길이, RSA_NO_PADING 최대 선 길이 = 128 바이트가 키의 키가 증가하면 암호화의 선 길이가 증가합니다.
현재 버전은 고정되어 있으며 EXE 버전 이상으로 컴파일 한 후 올바르게 작동합니다.
OpenSL 라이브러리를 통해 RSA 알고리즘을 사용하여 문자열의 암호화 / 암호 해독 구현을 통해 비밀 및 공개 파일을 PEM 형식으로 지정합니다.
1024 비트 키를 사용하면 rsa_pks1_padding = 117 바이트가있는 문자열 길이, rsa_no_pading을 사용하면 최대 문자열 길이 = 128 바이트입니다. 키 비트를 증가 시키면 암호화 스트링 길이가 증가합니다. 현재 버전이 수정되었으며 XE 버전 이상으로 컴파일 한 후에 올바르게 작동합니다.
개인 키를 생성하십시오
openssl genrsa 1024 > private.pem
개인에서 공개 키를 생성합니다
openssl rsa -in private.pem -pubout > public.pem
이니
OpenSSL_add_all_algorithms;
OpenSSL_add_all_ciphers;
OpenSSL_add_all_digests;
ERR_load_crypto_strings;
ERR_load_RSA_strings;파괴하다
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;키 파일 - 키/경로 키 ( '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 ;