Так и не удалось завести RSA в стандартном модуле, пришлось дергать ещё функции:
- Код: Выделить всё
- uses
 ...
 OpenSSL, dynlibs;
 type
 TPEM_write_bio_RSAPrivateKey = function(Pri: PBIO; KeyPair: PRSA;
 var1, var2, var3, var4, var5: pointer): integer; cdecl;
 TPEM_write_bio_RSAPublicKey = function(Pri: PBIO; KeyPair: PRSA): integer; cdecl;
 ...
 var
 PEM_write_bio_RSAPrivateKey: TPEM_write_bio_RSAPrivateKey;
 PEM_write_bio_RSAPublicKey: TPEM_write_bio_RSAPublicKey;
 implementation
 {$R *.lfm}
 procedure DoLoadOpenSSL;
 var
 hlib: TLibHandle;
 begin
 hlib := LoadLibrary(DLLSSLName + '.so');
 PEM_write_bio_RSAPrivateKey :=
 TPEM_write_bio_RSAPrivateKey(GetProcAddress(hlib, 'PEM_write_bio_RSAPrivateKey'));
 if PEM_write_bio_RSAPrivateKey = nil then
 ShowMessage('');
 PEM_write_bio_RSAPublicKey :=
 TPEM_write_bio_RSAPublicKey(GetProcAddress(hlib, 'PEM_write_bio_RSAPublicKey'));
 if PEM_write_bio_RSAPublicKey = nil then
 ShowMessage('');
 end;
 ...
 initialization
 DoLoadOpenSSL;
 end.
Дальше пошло чуть проще, генерация ключей:
- Код: Выделить всё
- function GenRsaKeys(KeySize: integer; var PriKey: string; var PubKey: string): PRSA;
 const
 PUB_EXP = 3;
 var
 PriLen, PubLen: integer;
 KeyPair: PRSA;
 Pri: PBIO;
 Pub: PBIO;
 begin
 KeyPair := RsaGenerateKey(KeySize, PUB_EXP, nil, nil);
 Pri := BioNew(BioSMem);
 Pub := BioNew(BioSMem);
 PEM_write_bio_RSAPrivateKey(pri, keypair, nil, nil, nil, nil, nil);
 PEM_write_bio_RSAPublicKey(pub, keypair);
 Prilen := BioCtrlPending(pri);
 Publen := BioCtrlPending(pub);
 SetLength(PriKey, PriLen + 1);
 SetLength(PubKey, PubLen + 1);
 BioRead(pri, PriKey, PriLen);
 BioRead(pub, PubKey, PubLen);
 BioFreeAll(pub);
 BioFreeAll(pri);
 Result := keypair;
 end;
Шифрование и расшифровка:
- Код: Выделить всё
- function EncryptRsa(KeyPair: PRSA; var OrigMsg: PByte; LenMsg: integer;
 var EncMsg: PByte; var EncLen: integer; var err: PChar): integer;
 begin
 EncLen := RSA_public_encrypt(LenMsg, OrigMsg, EncMsg, KeyPair, RSA_PKCS1_OAEP_PADDING);
 if EncLen = -1 then
 begin
 ERR_load_crypto_strings();
 Err_Error_String(ErrGetError(), err);
 Result := 0;
 end
 else
 Result := EncLen;
 end;
 function DecryptRsa(KeyPair: PRSA; var OrigMsg: PByte; var LenMsg: integer;
 var EncMsg: PByte; var EncLen: integer; var err: PChar): integer;
 begin
 LenMsg := RSA_private_decrypt(EncLen, EncMsg, OrigMsg, KeyPair,
 RSA_PKCS1_OAEP_PADDING);
 if LenMsg = -1 then
 begin
 ERR_load_crypto_strings();
 Err_Error_String(ErrGetError(), err);
 Result := 0;
 end
 else
 Result := LenMsg;
 end;
Ну и тестовый код демонстрации шифровки и расшифровки:
- Код: Выделить всё
 function GetHexTable(Buf: Pointer; iLen: integer): string;
 var
 i: integer;
 begin
 Result := '';
 for i := 0 to iLen do
 Result += IntToHex(integer(PByte(Buf + i)^), 2) + ', ';
 end;
 procedure TForm1.Button1Click(Sender: TObject);
 var
 PriKey: string;
 PubKey: string;
 RSA: PRSA;
 OrigMsg, EncMsg: PChar;
 EncLen: integer;
 err: PChar;
 OrigLen: integer;
 begin
 Memo.Clear;
 // Генерируем пару ключей
 PubKey := '';
 PriKey := '';
 RSA := GenRsaKeys(512, PriKey, PubKey);
 // Отображаем это в мемо
 memo.Append(PriKey);
 memo.Append('');
 memo.Append(PubKey);
 Memo.Append('');
 // Выделяем память
 Getmem(err, MAX_PATH);
 Getmem(OrigMsg, MAX_PATH);
 // Выводим оригинальное сообщение и закидываем это в буффер
 Memo.Append('--- ORIG MSG ---');
 Memo.Append('Hello World');
 strcopy(PChar(OrigMsg), PChar('Hello World'));
 OrigLen := strlen(OrigMsg);
 // Получаем будущий размер закодированных данных
 EncLen := RSA_size(RSA);
 GetMem(EncMsg, EncLen);
 // Кодируем данные
 EncLen := EncryptRsa(RSA, PBYTE(OrigMsg), OrigLen, PByte(EncMsg), EncLen, err);
 if EncLen = 0 then
 ShowMessage(err);
 // Выводим в HEX виде закодированные данные
 Memo.Append('');
 Memo.Append('--- ENCODED MESSAGE ---');
 Memo.Append(GetHexTable(EncMsg, EncLen));
 Memo.Append('');
 // Перезаписывем буфер
 Memo.Append('--- DESTROY BUFFER ---');
 Memo.Append('Destroy data in buffer (=');
 strcopy(PChar(OrigMsg), PChar('Destroy data in buffer (='));
 Memo.Append('');
 // Расшифровываем данные
 OrigLen := DecryptRsa(RSA, PBYTE(OrigMsg), OrigLen, PByte(EncMsg), EncLen, err);
 if OrigLen = 0 then
 ShowMessage(err);
 // Выводим расшифрованные данные
 Memo.Append('--- DECODED MSG ---');
 PByte(OrigMsg+OrigLen)^ := 0;
 Memo.Append(OrigMsg);
 // Освобождаем буферы за собой
 Freemem(err);
 Freemem(OrigMsg);
 Freemem(EncMsg);
 end;
Вроде всё работает, единственная проблема заключается в том, что я не могу (или не понимаю) как сохранить ключи и загрузить их обратно, буду очень признателен за помощь...
Добавлено спустя 5 часов 45 минут 58 секунд:
В общем вернувшись с работы, залез в доки и понял, что ключи вида
- Код: Выделить всё
- -----BEGIN RSA PRIVATE KEY-----
 -----BEGIN RSA PUBLIC KEY-----
Называются PEM ключами или ключами в PEM формате, соответственно их можно загрузить из памяти или из файла, что бы загрузить из файлы следует использовать функцию fopen и передавать в файловый дескриптор в
- Код: Выделить всё
- RSA *PEM_read_RSA_PUBKEY(FILE *fp, RSA **x, pem_password_cb *cb, void *u);
 ...
 и должно быть аналогично для private key
Но совместим ли FILE fpc и C?! хз, должен быть по идеи совместим, ведь дескрипторы выдаёт ОС, а вот как они хранятся в проге вот это без IDA не разберешь... По этому проще открыть файл или считать из БД в буфер и от него создать BIO_new_mem_buf и от него уже работать как с обычным BIO, исходника пока нет, я спать, если что выложу в своём блоге...


