12.10.2007 13:32:21Просмотр сертификата Ответов: 4
Влад
Здравствуйте.
Подскажите, пожалуйста, новичку какова последовательность действий и какие использовать функции CryptoAPI чтоб выполнить следующую задачу: получателю приходят зашифрованные сообщении сообщения от отправителей. Получателю необходимо убедиться, что отправитель именно тот, кто отправил (проверить сертификат отправителя) и просмотреть содержимое сертификата (серийный номер сертификата, ФИО (название) владельца сертификата и т.п.).
 
Ответы:
12.10.2007 13:55:38Kirill Sobolev
В зашифрованных сообщениях указывается получатель, а не отправитель. Возможно, Вы имели ввиду - подписанные?
12.10.2007 14:35:42Влад
Наверно я не четко рассказал о задаче:
1) Отправитель шифрует сообщение.
2) Подписывает:
...
CryptAcquireContext(@hProv, cont, provider_name, 75, 0)...
CryptCreateHash(hProv, CALG_GR3411, 0, 0, @hash)...
...
while not eof(infile) do
begin
BlockRead(infile, buf, 512, size);
BlockWrite(outfile, buf, size);
if not CryptHashData(hash, @buf, size, 0) then
begin msg:= 'Ошибка при хешировании: '); exit; end;
end;

CryptSignHash(hash, AT_KEYEXCHANGE{AT_SIGNATURE}, nil, 0, nil, @size)

GetMem(signature, size);
CryptSignHash(hash, AT_KEYEXCHANGE{AT_SIGNATURE}, nil, 0, signature, @size)...

BlockWrite(outfile, size, 4);
BlockWrite(outfile, signature^, size);

CryptDestroyHash(hash)..
CryptReleaseContext(hProv, 0)...

3) Получатель получает сообщение и может его расшифровать.
4) Проверяю подпись так:
...
CryptAcquireContext(@hProv, cont, provider_name, 75, 0)

...
//Файл подписи
BlockRead(infile, buflen_sign, 4);
BlockRead(infile, alg, 4);
BlockRead(infile, textsize, 4);
GetMem(pbuf_sign, textsize);
BlockRead(infile, pbuf_sign^, textsize, test);

if test < textsize then
begin msg:= 'Неверный формат файла! Процесс прерван.'; exit; end;
BlockRead(infile, test, 4);
GetMem(signature, test);
BlockRead(infile, signature^, test);

if not CryptCreateHash(hProv, CALG_GR3411, 0, 0, @hash) then
begin msg:= 'Ошибка создания хеш-объекта: '; exit; end;

if not CryptHashData(hash, bufs, textsize, 0) then
begin msg:= 'Ошибка при хешировании: '; exit; end;

//Файл ключа обмена ключами
BlockRead(infile, size, 4);
GetMem(signkey, size);
BlockRead(infile, signkey^, size);

if not CryptImportKey(hProv, signkey, size, 0, 0, @key) then
begin msg:= 'Ошибка импорта ключа: '; exit; end;

if CryptVerifySignature(hash, signature, test, key, nil, 0) then
begin msg:= 'Подпись не верна. '; exit; end;
...

Все работает. Но только есть сомнения:
а) правильно ли я проверяю подпись?
б) как узнать получателю что сертификат отправителя был валидный (не отозванный)?
в) получатель должен иметь возможность посмотреть данные сертификата отправителя (ФИО (название) владельца) Как в КриптоПРО - просмотреть сертификаты в контейнере.
12.10.2007 15:23:33Kirill Sobolev
Порядок иделогически не совсем верен. Отправителю надо сначала подписывать, а потом шифровать - иначе получается что он подписывает не сообщение,а какую-то белиберду, полученную после шифрования. С точки зрения криптографии подпись проверяется верно, но информации о подписчике в ней нет. Собственно, сертификат в алгоритме подписания у Вас и не используетя. Его надо добавлять вручную, что непросто, либо воспользоваться функциями более высокого уровня - CryptSignMessage, CryptVerifyMessageSignature.
05.11.2007 14:08:24Mike
Hi! Nice site! I wish you well!