06.04.2006 11:28:27Вопрос по подписям Ответов: 7
Антон Суслин
Здравствуйте!
Требуется подписать в своей программе некоторую строку текста из файла и добавить подпись в конец этого файла. Причем подпись должна быть в формате PKCS#7, и в ней должна содержаться информация о сертификате подписчика (имя, орг-ция и т.д.) - я так понимаю файлы с таким содержимым (.p7s) создает CryptoARM. Но мне это надо сделать средствами CryptoAPI с помощью CryptoPRO. Это осуществимо штатными средствами криптопровайдера? Если да, то какими? Или надо самому ручками создавать подпись со структурой, как в p7s?
 
Ответы:
06.04.2006 12:44:18Kirill Sobolev
Средствами CryptoAPI это будет сделать проще. Посмотрите CryptSignMessage
06.04.2006 12:50:35Василий
Именно так - "средствами CryptoAPI с помощью CryptoPRO". Т.е. Вы в программе вызываете нужные функции CryptoAPI.
Чем выше уровень вызываемых функций, тем меньше Вам работы как программису (но и меньше возможностей для настроек). Посмотрите готовый пример в описании в
MSDN ф-и CryptSignMessage.
06.04.2006 16:34:22Антон Суслин
Я так и сделал, по примерам с помощью данной функции реализовал подпись. Получаю 64-байтовую последовательность (? каждый раз почему то разную ?), которая просто является самой подписью. Мне нужно включать к неё также информацию из сертификата (если посмотреть получаемые cryptoarm файлы .p7s, то в них она как раз есть, а также есть, видимо, и открытый ключ подписавшего? ). Я насколько понимаю формат PKCS#7 - это именно то, что мне нужно. Вопрос собственно именно в этом - можно ли создать подпись сразу в этом формате?
06.04.2006 16:36:11Kirill Sobolev
CryptSignMessage именно это и должна делать.
Можете свой пример кода привести?
06.04.2006 16:57:18Антон Суслин
Пожалуйста:

BYTE *data= (BYTE *)"The data that is to be hashed and signed.";

HCRYPTPROV hProv = 0;
HCRYPTHASH hHash = 0;

if(!CryptAcquireContext(&hProv, NULL, NULL, 75, 0)) {
// обработка ошибки
return;
}

if(!CryptCreateHash(hProv, CALG_GR3411, 0, 0, &hHash)) {
// обработка ошибки
CryptReleaseContext(hProv, 0);
return;
}

DWORD cbHash = 0;

if(!CryptGetHashParam(hHash, HP_OID, NULL, &cbHash, 0)) {
// обработка ошибки
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return;
}

BYTE *pbHash = (BYTE *)malloc(cbHash);

if(!CryptGetHashParam(hHash, HP_OID, pbHash, &cbHash, 0)) {
// обработка ошибки
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return;
}


if(!CryptHashData(hHash, data, sizeof(data), 0)) {
// обработка ошибки
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return;
}

DWORD dwSigLen = 0;
if(!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, NULL, &dwSigLen)) {
// обработка ошибки
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return;
}
BYTE *pbSignature;
pbSignature = (BYTE *)malloc(dwSigLen);

if(!CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)) {
// обработка ошибки
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);
return;
}

free(pbHash);
free(pbSignature);
CryptReleaseContext(hProv, 0);
CryptDestroyHash(hHash);

Собсно, в pbSignature получаем непонятно что и каждый раз новое... :( Отрабатывается все без ошибок.
Конечно, не сомневаюсь, что где-то моя ошибка, а где - никак не пойму...
06.04.2006 17:04:00Kirill Sobolev
Нескромный вопрос, Антон, а Вы вообще читали то, что Вам ответили и Василий и я? Разговор шел не про набор низкоуровневых функций а про вполне конкретную CryptSignMessage, которая делает все то же что и Ваш код + выдает нужный Вам PKCS7.
То, что подпись каждый раз разная это абсолютно верно и заложено в самом алгоритме подписи.
06.04.2006 17:09:52Антон Суслин
Приношу свои извинения, господа! Совсем заработался и не нашел отличий между CryptSignHash и CryptSignMessage...

Большое спасибо за помощь и ещё раз извините за невнимательность! :) Будем копать CryptSignMessage...