Методы криптографической защиты информации Windows
Рассмотрим пример создания ключевых пар при помощи формы. В поле "Контейнер" можно указать имя контейнера ключей; если оставить это поле пустым, будет использован контейнер по умолчанию. Назначение остальных элементов управления должно быть интуитивно понятным. После генерации ключа в memo-поле выводится отчет о его параметрах. Для этого используется функция CryptGetKeyParam (ключ, параметр, буфер, размер, флаги). Чтобы получить информацию о требуемом параметре, нужно через второй аргумент функции передать соответствующую константу: KP_ALGID - идентификатор алгоритма, KP_KEYLEN - размер ключа, и т. д. Ниже приведен текст процедуры генерации ключей без операторов обработки ошибок:
var
cont: PChar;
err: string;
hProv: HCRYPTPROV;
KeyExchKey, SignKey: HCRYPTKEY;
flag, keyLen: DWORD;
begin
{если ни один ключ не выбран - выход}
if not (KEKCheckBox.Checked or SKCheckBox.Checked) then
exit;
{"считываем" имя контейнера}
if length(ContainerEdit.Text) = 0 then
cont := nil
else
begin
err := ContainerEdit.Text;
cont := StrAlloc(length(err) + 1);
StrPCopy(cont, err);
end;
CryptAcquireContext(@hProv, cont, nil, PROV_RSA_FULL, 0);
{генерация ключа обмена ключами (Key Exchange Key)}
if KEKCheckBox.Checked then
begin
{"считываем" длину ключа и помещаем ее в
старшее слово параметра ФЛАГИ}
keyLen := strtoint(KeyExchLenEdit.text);
flag := keyLen shl 16;
if not CryptGenKey(hProv, AT_KEYEXCHANGE, flag, @KeyExchKey) then
begin
јобработка ошибокј
end
else
begin
ReportMemo.Lines.Add('');
ReportMemo.Lines.Add('Создан ключ обмена ключами:');
flag := 4;
if not CryptGetKeyParam(KeyExchKey, KP_KEYLEN, @keyLen, @flag, 0) then
begin
јобработка ошибокј
end
else
ReportMemo.Lines.Add(' длина ключа - ' + inttostr(keyLen));
flag := 4;
if not CryptGetKeyParam(KeyExchKey, KP_ALGID, @keyLen, @flag, 0) then
begin
јобработка ошибокј
end
else
ReportMemo.Lines.Add(' алгоритм - ' + algIDtostr(keyLen));
{функция algIDtostr здесь не приводится. Она состоит из единственного
оператора case, отображающего целый идентификатор алгоритма в строку}
end;
end;
{генерация ключа подписи (Signature Key)}
if SKCheckBox.Checked then
begin
јвыполняется аналогично генерации ключа обмена ключамиј
end;
CryptReleaseContext(hProv, 0);
end;
Обмен ключами
Теперь мы располагаем набором ключей, однако все они останутся мертвым грузом, до тех пор пока мы не получим возможности обмена с другими пользователями открытыми ключами. Для этого необходимо извлечь их из базы данных ключей и записать в файл, который можно будет передать своим корреспондентам. При экспорте данные ключа сохраняются в одном из трех возможных форматов:
PUBLICKEYBLOB - используется для сохранения открытых ключей. Поскольку открытые ключи не являются секретными, они сохраняются в незашифрованном виде;
PRIVATEKEYBLOB - используется для сохранения ключевой пары целиком (открытого и закрытого ключей). Эти данные являются в высшей степени секретными, поэтому сохраняются в зашифрованном виде, причем для шифрования используется сеансовый ключ (и, соответственно, симметричный алгоритм);
SIMPLEBLOB - используется для сохранения сеансовых ключей. Для обеспечения секретности данные ключа шифруются с использованием открытого ключа получателя сообщения.
Экспорт ключей в CryptoAPI выполняется функцией CryptExportKey (экспортируемый ключ, ключ адресата, формат, флаги, буфер, размер буфера):
экспортируемый ключ - дескриптор нужного ключа;
ключ адресата - в случае сохранения открытого ключа должен быть равен нулю (данные не шифруются);
формат - указывается один из возможных форматов экспорта (PUBLICKEYBLOB, PRIVATEKEYBLOB, SIMPLEBLOB);
флаги - зарезервирован на будущее (должен быть равен нулю);
буфер - содержит адрес буфера, в который будет записан ключевой BLOB (Binary Large OBject - большой двоичный объект);
размер буфера - при вызове функции в этой переменной должен находиться доступный размер буфера, а по окончании работы в нее записывается количество экспортируемых данных. Если размер буфера заранее не известен, то функцию нужно вызвать с параметром буфер, равным пустому указателю, тогда размер буфера будет вычислен и занесен в переменную размер буфера.
Экспорт ключевой пары целиком, включая и закрытый ключ, может понадобиться для того, чтобы иметь возможность подписывать документы на различных компьютерах (например, дома и на работе), или для сохранения страховочной копии. В этом случае нужно создать ключ шифрования на основании пароля (см. "К+П", № 10/2002) и передать дескриптор этого ключа в качестве второго параметра функции CryptExportKey.
Запросить у криптопровайдера дескриптор самого' экспортируемого ключа позволяет функция CryptGetUserKey (провайдер, описание ключа, дескриптор ключа). Описание ключа - это либо AT_KEYEXCHANGE, либо AT_SIGNATURE.
Экспорт асимметричных ключей во всем возможном многообразии можно осуществить при помощи формы.
Отправить комментарий