Методы криптографической защиты информации Windows
Ниже приведены наиболее важные фрагменты программы:
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). Флаги в настоящее время также не используются - на месте этого аргумента должен быть нуль. Готовую электронную подпись функция запишет в буфер, адрес которого содержится в предпоследнем параметре, последний же параметр будет содержать длину подписи в байтах.
Отправить комментарий