По долгу службы в разработчиках повстречалась задача шифровать текстовые строки алгоритмом RSA, используя публичный и секретный ключи в PEM формате. При изучении данного вопроса выбор пал на использование библиотеки OpenSSL. Хочу поделиться примерами реализации функциональности шифрования на Delphi. Действия выполнялись в ОС Windows, среда разработки Borland Delphi 7.

С чего начать?


В первую очередь необходим пакет openssl, а точнее библиотека libeay32.dll. И для подключения библиотеки нам понадобится готовый юнит libeay32.pas, который необходимо подключить к проекту. В моем примере отсутствует функциональность генерации ключей из проекта, как это сделать можно будет почитать в материале по ссылке снизу статьи. Для генерации пары ключей я использовал сам openssl следующими командами из cmd:
Генерируем приватный ключ и из него извлекаем публичным ключ
openssl genrsa 1024 > private.pem
openssl rsa -in private.pem -pubout > public.pem

Где 1024 является битностью ключа. Отмечу, что от битности ключа зависит и длина строки для шифрования. Если ключ 1024 бита, то зашифровать сможем всего 128 байт, тот самый размер, которому равен размеру ключа. Ниже покажу функцию, определяющие размер структуры RSA ключа. Но это не все. Данный буфер уменьшится на 11 байт, если во время шифрования указать параметр padding, отвечающего за выравнивания данных — PKCS#1.

Сгенерировав ключ в 2048 бит, сможем зашифровать 256 байт. При этом увеличивается размер выходного шифрованного текста, даже если будет зашифрован всего 1 байт.

Для моей задачи было достаточно 117 байт, в которые умещались карточные данные, размер строк в базе, конечно же, значительно вырос. Но того требует безопасность.

Основные функции


Основное, что мы будем использовать для шифрования, — это:

Инициализация крипто функций

OpenSSL_add_all_algorithms;
OpenSSL_add_all_ciphers;
OpenSSL_add_all_digests;
ERR_load_crypto_strings;
ERR_load_RSA_strings;

Destroy

EVP_cleanup; 
ERR_free_strings;

Чтение ключей

//чтение секретного ключа в формате PEM, возвращает структуру RSA
//Где bp файл ключа, возвращаемый в RSA структуру указывающей x, cb – адрес функции запрашиваемая пароль к ключу. 
function PEM_read_bio_PrivateKey(bp: pBIO; var x: pEVP_PKEY;
    cb: TPWCallbackFunction; u: pointer): pEVP_PKEY; cdecl;

//чтение публичного ключа в формате PEM, возвращает структуру RSA
function PEM_read_bio_PUBKEY(bp: pBIO; var x: pEVP_PKEY;
    cb: TPWCallbackFunction; u: pointer): pEVP_PKEY; cdecl;

И функции шифрации/дешифрации

//Шифрование/дешифрование flen размера буфера from в буфер _to используя структуру RSA ключа загруженного ранее в режиме выравнивания 
//данных padding. Получаем длину шифрованного/дешифрованного буфера или -1 при ошибке
//Шифрование публичным ключом
function RSA_public_encrypt(flen: integer; from: PCharacter; _to: PCharacter; rsa: pRSA; padding: integer): integer; cdecl;

//Шифрование секретным ключом
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_private_decrypt(flen: integer; from: PCharacter; _to: PCharacter; rsa: pRSA; padding: integer): integer; cdecl;

Приступим к реализации


Итак, мы имеем сгенерированные ключи, dll-ка лежит в папке с проектом, liblea32.pas подключен в uses. Вызываем процедуры инициализации openssl:

procedure LoadSSL;
begin
  OpenSSL_add_all_algorithms;
  OpenSSL_add_all_ciphers;
  OpenSSL_add_all_digests;
  ERR_load_crypto_strings;
  ERR_load_RSA_strings;
end;

procedure FreeSSL;
begin
  EVP_cleanup;
  ERR_free_strings;
end;

Пишем функции загрузки ключей.

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;

И заключении пример чтения ключа «зашитого» в приложение

В примере указан приватный ключ и его чтение, с таким же успехом «зашивается» и читается публичный ключ функцией PEM_read_bio_PUBKEY
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;

На этом мои примеры реализации заканчиваются. Исходники проекта доступны на Github.

Иточники:



UPD
Из дискуссий в комментариях внесу дополнения: если мы зашифровываем нужную нам строку публичным ключом, то расшифровывается она только секретным и наоборот — если секретным, то расшифровать можно только публичным ключом. В моем случае у клиента публичный ключ, которым он шифрует данные и только на сервере их можно расшифровать секретным ключом.

Комментарии (27)


  1. ValdikSS
    28.03.2016 11:04
    +4

    Вы уверены, что понимаете, что вы делаете? Функции RSA_private_encrypt и RSA_public_decrypt, несмотря на их название, работают с подписями, а не с шифрованием (с точки зрения RSA, дешифровка публичным ключом является подписью, а шифрование приватным — проверкой подписи).


    1. StrangerInRed
      28.03.2016 11:14

      Легчайше. RTFM!


    1. StrangerInRed
      28.03.2016 11:21

      Совет на будуще когда имплементите незнакомое шифрование пишите для него тесты где проверяйте для разных данных length(data) == length(encrypted message). В подписе и хеше length(encrypted) всегда будет const для разной длинны data.


    1. Kolyuchkin
      28.03.2016 11:23

      Согласен с Вами насчет непонимания автора. Фактически, исходя из логики алгоритмов ЭП, «шифруется и расшифровывается» результат необратимой функции (ХЭШ), а он, автор, пихает вместо ХЭШ-а текстовую строку… Не одобряю я такое… Это все равно, что в стиральной машине тесто месить — можно, но зачем?


      1. ValdikSS
        28.03.2016 11:36
        +7

        Да дело не в этом. Автор пытается использовать RSA в качестве какого-то симметричного шифра, фактически не используя свойство асимметрии, и, вероятно, из-за непонимания процесса, описывает это в качестве правильного способа использования RSA.

        Вот никогда не жаловался на статьи, но это теперь уже, похоже, уровень хабра 2016 года. НЛО должно быть стыдно за то, что за такую статью теперь можно инвайт получить.


        1. Kolyuchkin
          28.03.2016 11:42
          +1

          Вот и добавить нечего))))) Все в точку)))))


          1. toxicdream
            28.03.2016 13:37

            Нда уж…
            Читаешь и прям руки чешутся самому написать статью.
            Но:
            1) нет времени
            2) а зачем? кому надо тот сам дойдет — в инете вагон и тележка примеров.
            Как-то пришлось переводить один продукт с OpenSSL на SSPI.
            В итоге замучившись с трансляцией заголовочных файлов из C++ на Pascal/Delphi, взяли готовый продукт.
            Толи Secure Black Box, толи Internet Clever Suite — уже не помню.
            Чего и другим советую, когда цена ошибки слишком велика по сравнению с ценой на эти продукты.


        1. Lence
          28.03.2016 15:57

          Развею догадки. Понимание вопроса имеется. В статье описывается способ реализации RSA от Open SSL конкретно в Delphi. Но никак не призыв того как правильно или неправильно использовать именно алгоритм RSA. Да, RSA используют для сверки подписей, ХЭШей. Но кто сказал, что не могу зашифровать, к примеру, серийный номер карты на клиенте, передать его в зашифрованном виде не сервер и только сервер может расшифровать переданные данные, если длина серийного номера удовлетворяет нужному размеру и крипто стойкости в 1024 бита мне хватает?


          1. ValdikSS
            28.03.2016 17:14
            +1

            передать его в зашифрованном виде не сервер и только сервер может расшифровать переданные данные
            В том-то и дело, что не только сервер сможет расшифровать переданные данные, а кто угодно, обладающий публичным (а не приватным!) ключом.

            Как обычно работает RSA: данные шифруются публичным ключом, расшифровываются приватным. Публичный можно, скажем, вшить в программу, и в этом случае, действительно, никто не сможет расшифровать данные, даже обладая программой.

            Вы же, однако, используете подписи так, словно это и есть данные: вы дешифруете открытый текст (будто это уже шифрованный текст) приватным ключом, а чтобы его расшифровать, наоборот, шифруете текст публичным ключом.

            Таким образом, чтобы зашифровать текст, вам нужно вшить приватный ключ в программу, а не публичный, а получить публичный из приватного — плевое дело. И любой человек, имеющий эту програму и способный достать из нее приватный ключ (а это несложно), способен расшифровывать данные.

            Так что, боюсь, вы действительно не понимаете, что делаете.


            1. Lence
              28.03.2016 17:36

              Вы в правду считаете, что я буду шифровать данные секретным ключом на клиенте и передавать их в таком виде? Если конкретно в моем случае, то с клиентом рядом идет публичный ключ, а приватный находится на сервере. В конце статьи я показал пример как «вшить» ключ в программу. Еще раз — это примеры, как туда/обратно зашифровать/расшифровать приватным/публичным ключами, на Delphi используя OpenSSL. А не то как я реализовал проект, правильно или нет. Суть статьи не в том, как правильно шифровать: вначале публичным и секретным расшифровывать или наоборот. Все зависит от задачи.
              Я смог внести ясность в то, что понимаю о чем пишу?


              1. ValdikSS
                28.03.2016 17:48
                +3

                Я вас не понимаю. Если это примеры, то почему они неправильные? Еще раз: у вас в статье шифрование осущеставляется приватным ключом, а расшифрование — публичным


                1. Lence
                  28.03.2016 18:10

                  Ясно. Я понял о чем Вы. Взгляните пожалуйста на Github. Утилитка, которая написана имеет 4 кнопки: Public Encrypt и для нее Private Decrypt. И отдельно Private Encrypt и для нее Public Decrypt. Для того чтоб показать: если зашифровать Публичным, то расшифровать можно только Приватным и если зашифровать Приватным, то расшифровать можно только Публичным. Конкретно в моем проекте — Публичным ключом шифруется, а Приватным расшифровывается. Я отредактирую куски, которые смущают.


                  1. ComradeAndrew
                    28.03.2016 18:25
                    +1

                    Я вот тоже не понял. Зачем вы вообще показываете пример с шифрованием приватным ключом в ассиметричной системе шифрования? Тем более, раз утверждаете, что сами так не делаете.


                    1. Lence
                      28.03.2016 18:30

                      На самом деле в полном исходном коде реализованы оба способа, как я написал в комментарии выше. Но для ясности подправил исходники и добавил комментарий.


                  1. ValdikSS
                    28.03.2016 22:13

                    и если зашифровать Приватным, то расшифровать можно только Публичным
                    Я надеюсь, вы понимаете, что публичный можно получить из приватного?

                    Как бы технически можно, конечно, шифровать приватным ключом (дешифровать, на самом деле) и расшифровать публичным (а тут на самом деле шифровать), но для данных это совершенно не подходит, т.к. любой, кто владеет приватным ключом, сможет совершать оба действия, вы же понимаете это?

                    Даже с технической точки зрения, если смотреть со стороны низкого уровня, у вас кнопки делают не то, что на них написано: Private Crypting будет на самом деле расшифровывать данные приватным ключом, а Public Decrypting наоборот, зашифровывать. Именно поэтому у вас образуется «мусор» в виде паддинга, т.к. Public Decrypting (который на самом деле Encrypting) логично считает, что на вход ему подали открытое сообщение, а у вас оно получается уже с паддингом.


                    1. Lence
                      28.03.2016 22:54

                      Конечно же я прекрасно понимаю, что из приватного получается публичный, именно таким образом в статье я сгенерировал ключи. Мне казалось это очевидным. Вначале приватный, затем извлек публичный.
                      Давайте я приведу пример — когда множество клиентов по офису, которые получают сообщения от сервера, будь то настройки или еще какие либо команды. В этом случае сервер имея приватный ключ, шифрует ( по вашей терминологии расшифровывает) сообщение, для клиентов. А клиент, приняв такое сообщение успешно его расшифрует (зашифрует с ссылкой на Вас) публичным ключом и будет точно уверен, что сообщение отправил именно сервер. Поэтому пример работает в обе стороны.
                      Что касается мусора (это в обоих функциях decrypting публичным или приватным, в приватном точно так) — изначально для data задается размер (в моем примере 128 байт), после дешифрации в data попадает, допустим, всего 27 байт (строка маленькая), остальное место в data остается бинарным мусором. Никак не связанно с паддингом.
                      В статье исправил порядок функций, чтоб не было путаницы в понимании. Я не стал с самого начала описывать, что такое RSA. цель была в другом, ссылку на отличную статью я привел в конце. Видимо вкратце надо было немного написать.


                      1. Lence
                        28.03.2016 23:05

                        Сверка подписи именно таким образом и происходит. Отправителем шифруется приватным ключом и клиент публичным ключом сверяет подпись.


                      1. ValdikSS
                        29.03.2016 13:20

                        Хм, ну можно так, да.


            1. Lence
              28.03.2016 17:45

              Вас видимо смутил пример с «вшитым» ключом, где как раз приватный ключ в константе, поэтому Вы решили, что с клиентом идет приватный? Публичный ключ у клиента. И он даже не вшит, всегда скачивается, потому, что в любой момент ключи могут поменяться


  1. Kolyuchkin
    28.03.2016 11:37
    -4

    Уважаемый автор, у меня к Вам есть один главный вопрос и несколько второстепенных. Главный: «Зачем Вы используете криптографию, не разобравшись что к чему?»
    Второстепенные: 1) «Если Вы пишете под Windows да еще используете „буржуйские“ криптоалгоритмы, то не проще ли использовать для этого нативный для Windows крипто-сервис-провайдер? Он „искаропки“ присутствует.»
    2) «Если Вы заботитесь о безопасности, то почему Вам разрешили на территории РФ (из слов „по долгу службы“ я понял, что это работа под заказчика, не Ваша инициатива… хотя, „шифровать текстовые строки алгоритмом RSA“ отдают амбре профанации либо Вас, либо Вашего заказчика) использовать „буржуйские“ криптоалгоритмы? На этот вопрос можете не отвечать, если Вы разрабатывали курсовик или лабораторку для кого-то.»


    1. Lence
      28.03.2016 23:35

      Разобравшись. В статье есть дополнения. Проще мне было реализовать на openssl. По Windows крипто провайдеру тоже есть прекрасная статья с примерами реализации на Delphi. Но речь не об выборе. OpenSSL open source, а Windows крипто провайдер куда сольет данные?
      Я не из РФ, кто Вам в РФ запрещает? Законы? Религия?


      1. Kolyuchkin
        29.03.2016 09:24

        Видимо, не до конца разобравшись, все-таки. Разъясняю, вкратце:
        1) асимметричные криптоалгоритмы, и по логике и по устоявшимся правилам и по скорости, предназначены для двух «вещей»: 1) формирование и проверка электронной подписи (там как по Вашему шифруется и расшифровывается отпечаток блока открытых данных — иными словами ХЭШ); 2) криптосхемы с открытым распределением ключей (там уже шифруется и расшифровывается (либо по Диффи-Хелману, либо по Эль-Гамалю) ключ симметричного криптоалгоритма, на котором зашифрован блок открытой информации);
        2) если уж Вы решили хранить приватный ключ в коде в виде константы, то зачем Вам беспокоиться о «недокументированном поведении» дефолтного для Windows криптопровайдера?
        3) в РФ разрешено использовать только отечественные криптоалгоритмы, если Вы хотите попасть под защиту законодательства РФ в сфере информационной безопасности (если Вы не из РФ, то Вам это и не нужно)…

        Приношу извинения за то, что, не разобравшись, комментировал Вашу разработку с той точки зрения, что Вы находитесь в РФ и, возможно, зря обвинил Вас за «не РФ-овское» использование крипоалгоритмов (все касается только информационной безопасности в ее правовой и законодательной сфере). Так что, из всего выходит, я начал консультировать иностранного гражданина)))))

        З.Ы. вот уже зазвонил сотовый без СИМ-ки и аккумулятора) наверное это «младшие братья» «вежливых людей»)))


        1. Lence
          29.03.2016 12:48

          1) Хочу привести цитату из статьи, ссылка на нее в конце топика:
          Криптосистема RSA, предложенная в 1977 году Ривестом (R. Rivest), Шамиром (A. Shamir) и Адлеманом (L. Adleman), предназначена для шифрования и цифровой подписи. В настоящее время RSA является наиболее распространенной криптосистемой — стандартом де-факто для многих криптографических приложений. Криптосистема RSA широко применяется в составе различных стандартов и протоколов Интернета, включая PEM, S/MIME, PEM-MIME, S-HTTP и SSL. Т.е. необязательно для ЭЛ, хотите криптуйте секретным ключом пароль для всего остального сообщения, хотите сравнивайте ХЭШ сообщения итд.
          У меня в одном из проектов клиент генерирует md5 из данных в полученной xml, расшифровывает публичным ключом подпись от сервера, тоже в md5, сравнивает. Далее после определенных действий генерирует xml в ответ, в котором содержится сгенерированный md5, зашифрованный публичным ключом. На сервере может быть аппликация с «вшитым» секретным ключом, может висеть PHP скрипт с «вшитым» секретным ключом.
          2) Вопрос не о выборе, что использовать, Windows крипто провайдер, OpenSSLили отечественную разработку. Как и не вопрос на чем реализовывать. Вопрос в примере — Delphi + OpenSSL. Как написали выше примеров на Delphi не вагон и тележка, с/с++ да. На Delphi кусочки какие-то. Зашифровать только, а расшифровать?
          3) Но примеры то не запрещены?

          P.S. я поделился примерами как использовать RSA от OpenSSL в проектах на Delphi, звонить Вам с тапка на выключенный мобильник не буду )))


  1. mefest
    28.03.2016 13:23
    -3

    На сколько тяжелые библиотеки OpenSSL?
    Во времена универа мы сами реализовывали rsa алгоритм, там довольно простой алгоритм.Насколько больше выгода от использования OpenSSL?


    1. SannX
      29.03.2016 16:46
      +2

      В области инф. безопасности лучше не изобретать велосипеды — это чревато дырами. В универе для обучения можно и писать самому такие алгоритмы, а вот в продакшине лучше использовать готовые, хорошо протестированные библиотеки/решения. Потому размер тут не главное.


  1. Eugene75
    28.03.2016 14:45
    +1

    Совсем забыли о Delphi, спасибо за полезную статью.


  1. leremin
    28.03.2016 23:56

    В репе есть примечание "Для компиляции в XE необходимо поменять типы у входящих параметров"… Почему нельзя использовать {$IFDEF VERXXX}?