การอนุรักษ์/ถอดรหัสบรรทัดที่มีอัลกอริทึม RSA ผ่านห้องสมุด OpenSSL ที่ระบุไฟล์ลับและคีย์สาธารณะในรูปแบบ PEM
ด้วยคีย์ของ 1024 บิตความยาวของเส้นที่ RSA_PKS1_PADDING = 117 ไบต์ด้วย RSA_NO_PADING ความยาวเส้นสูงสุด = 128 ไบต์โดยเพิ่มคีย์ของคีย์เพิ่มความยาวเส้นสำหรับการเข้ารหัส
เวอร์ชันปัจจุบันได้รับการแก้ไขและทำงานได้อย่างถูกต้องหลังจากการรวบรวมในรุ่น EXE และสูงกว่า
การใช้งานการเข้ารหัส / ถอดรหัสของสตริงโดยใช้อัลกอริทึม RSA ผ่านไลบรารี OPENSL โดยระบุความลับและไฟล์สาธารณะในรูปแบบ 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;KeyFile - ไปที่คีย์/เส้นทางคีย์ ('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 ;