Методы криптографической защиты информации Windows

Ниже приведены наиболее важные фрагменты программы:

procedure TExportForm.OKBtnClick(Sender: TObject);
var
 cont: PChar;
 err: string;
 hProv: HCRYPTPROV;
 key, expKey: HCRYPTKEY;
 pbuf: PBYTE;
 buflen: DWORD;
 f: file;
 hash: HCRYPTHASH;
begin
 {если ни один ключ не выбран - выход}
 if not (KEKCheckBox.Checked or SKCheckBox.Checked) then
  exit;
 {если нужен пароль, т.е. экспортируется ключевая пара целиком}
 if PasswEdit.Enabled and (PasswEdit.Text < > Passw2Edit.Text) then
 begin
  MessageDlg('Ошибка при вводе пароля! Повторите ввод.', mtError, [mbOK], 0);
  exit;
 end;


"считываем" имя контейнера и подключаемся к криптопровайдеру

если нужен ключ шифрования - создаем его на основании пароля

{ключ обмена ключами}

if KEKCheckBox.Checked then

 repeat

  {получаем дескриптор ключа}

  CryptGetUserKey(hProv, AT_KEYEXCHANGE, @key);

  {пытаемся определить размер буфера для экспорта ключа}

  if (WhatRadioGroup.ItemIndex = 0) then

  CryptExportKey(key, 0, PUBLICKEYBLOB, 0, nil, @bufLen)

  else

  CryptExportKey(key, expKey, PRIVATEKEYBLOB, 0, nil, @bufLen);

  GetMem(pbuf, bufLen);

  {экспортируем данные}

  if (WhatRadioGroup.ItemIndex = 0) then

  CryptExportKey(key, 0, PUBLICKEYBLOB, 0, pbuf, @bufLen)

  else

  CryptExportKey(key, expKey, PRIVATEKEYBLOB, 0, pbuf, @bufLen);

  {освобождаем дескриптор ключа обмена ключами

  (сам ключ при этом не уничтожается)}


  CryptDestroyKey(key);

  SaveDialog1.Title := 'Укажите файл для сохранения ключа обмена ключами';

  if SaveDialog1.Execute then

  begin

  AssignFile(f, SaveDialog1.FileName);

  rewrite(f, 1);

  BlockWrite(f, pbuf^, bufLen);

  CloseFile(f);

  MessageDlg('Ключ обмена ключами успешно сохранен', mtInformation, [mbOK],

  0);

  end;

 until true; {KeyExchange}

{ключ подписи}

if SKCheckBox.Checked then

 repeat

  јаналогично ключу обмена ключамиј

 until true; {Signature}

end;


если создавался ключ на основании пароля - уничтожаем его,
после чего освобождаем контекст криптопровайдера

Экспортированные таким образом открытые части ключей понадобятся нам для проверки подписи и расшифровки сеансового ключа.
Импорт ключевых пар во вновь созданный контейнер - это самостоятельная процедура. Необходимо запросить у пользователя название контейнера и пароль, подключиться к провайдеру, создать на основании пароля ключ, считать из файла импортируемые данные в буфер, после чего воспользоваться функцией CryptImportKey (провайдер, буфер, длина буфера, ключ для расшифровки, флаги, импортируемый ключ). Если нужно обеспечить возможность экспорта импортируемой ключевой пары впоследствии, то в параметре флаги необходимо передать значение CRYPT_EXPORTABLE; в противном случае вызов для данной ключевой пары функции CryptExportKey приведет к ошибке.
Мы уже обсуждали, что при работе с асимметричными алгоритмами важно убедиться, что открытый ключ действительно принадлежит тому, кого вы считаете его хозяином, и не был подменен злоумышленником. Простейшим способом обеспечить аутентичность ключа является побайтная сверка с оригиналом, хранящимся у его хозяина. Для этого можно просто позволить пользователю просмотреть экспортированные данные в шестнадцатеричном виде - например, открыть файл, в который был записан открытый ключ, и вывести его содержимое в окно просмотра.
Электронная цифровая подпись
Для создания электронной цифровой подписи необходимо вычислить хеш заданного файла и зашифровать этот "цифровой отпечаток сообщения" своим закрытым ключом - "подписать". Чтобы подпись впоследствии можно было проверить, необходимо указать, какой алгоритм хеширования использовался при ее создании. Поэтому подписанное сообщение должно иметь структуру.
Подписать вычисленный хеш в CryptoAPI позволяет функция CryptSignHash (хеш, описание ключа, комментарий, флаги, подпись, длина подписи). Вторым параметром может быть либо AT_KEYEXCHANGE, либо AT_SIGNATURE (в нашем случае логичнее использовать ключ подписи). Третий параметр в целях безопасности настоятельно рекомендуется оставлять пустым (nil). Флаги в настоящее время также не используются - на месте этого аргумента должен быть нуль. Готовую электронную подпись функция запишет в буфер, адрес которого содержится в предпоследнем параметре, последний же параметр будет содержать длину подписи в байтах.

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...