06.06.2003 10:42:58непонятки с типом Ответов: 4
Абшарипов Ильшат
Непонятная ошибка. Функция CryptSignMessage требует в качестве последнего параметра (размера буфера) значение типа DWord, однако при попытке передать ей переменную именно этого типа, она возвращает какую-то чушь (что-то около 8млн), если же передать переменную типа Byte, то возвращается нормальное значение, только при повторном вызове функции уже для подписывания, вылетаем с ошибкой «Не понял» («The function failed in some unexpected way»). Где что не так?

Привожу кусок кода:
var
SignParams: CRYPT_SIGN_MESSAGE_PARA;
SignedData: PByte;
SignedDataLen: DWord;
Buf: PByteArray;
BufLen: DWordArray;
SD: array of byte;
begin
Result := False;

//размер структуры в байтах
SignParams.cbSize := SizeOf(CRYPT_SIGN_MESSAGE_PARA);
//тип кодирования
SignParams.dwMsgEncodingType := X509_ASN_ENCODING or PKCS_7_ASN_ENCODING;
//указатель на контекст сертификата
SignParams.pSigningCert := CertContext;
//используемый алгоритм хэширования
SignParams.HashAlgorithm.pszObjId := szOID_CP_GOST_R3411_R3410;
//флаг - не показывать диалог CSP
SignParams.dwFlags := 0;
//показывает на тип шифрования сообщения, если подписываемое сообщение
//является результатом предыдущей криптографической функции
SignParams.dwInnerContentType := 0;
//количество элементов в массиве rgpMsgCert + массив указателей на включаемые CERT_CONTEXT (сертификаты)
SignParams.cMsgCert := 0;
SignParams.rgpMsgCert := nil;
//количество элементов в массиве rgpMsgCrl + массив указателей на включаемые CRL_CONTEXT (список отозванных сертификатов)
SignParams.cMsgCrl := 0;
SignParams.rgpMsgCrl := nil;
//кол-во элементов в массиве rgAuthAttr + массив указателей на включаемые CRYPT_ATTRIBUTE (информация аутентификации)
SignParams.cAuthAttr := 0;
SignParams.rgAuthAttr := nil;
//кол-во элементов в массиве rgUnauthAttr + массив указателей на включаемые CRYPT_ATTRIBUTE (информация не для аутентификации)
SignParams.cUnauthAttr := 0;
SignParams.rgUnauthAttr := nil;
//не используется
SignParams.pvHashAuxInfo := nil;

//будем подписывать только одно сообщение
SetLength(Buf, 1);
SetLength(BufLen, 1);
//это наше сообщение
SetLength(SD, 3);
SD[0] := Ord(’1’);
SD[1] := Ord(’2’);
SD[2] := Ord(’3’);

Buf[0] := @SD[0];
BufLen[0] := memInner.Size;
if not CryptSignMessage(@SignParams, False, 1, Buf, BufLen, nil, @SignedDataLen) then
begin
//обрабатываем ошибку, но здесь не вылетаем
Exit;
end;
//подписываем
GetMem(SignedData, SignedDataLen);
if not CryptSignMessage(@SignParams, False, 1, Buf, BufLen, SignedData, @SignedDataLen) then
begin
//тут снова обработка ошибки
//в этом блоке-то и происходит вылет
Exit;
end;
 
Ответы:
06.06.2003 13:18:21Олег
кстати на счет
SignParams.HashAlgorithm.pszObjId := szOID_CP_GOST_R3411_R3410;

Чего то я где то читал что CP CSP на этот параметр нещадно забивает - ставит правильный в любом случае. Меня бы это очень устроило - поставил бы SHA1 и моя бы функция не задумывалась бы об алгоритме сертификата которым подписываем.
И тем не менее - что будет если в нашей подписи будет вражеский алгоритм хэширования? Что нам закон об ЭЦП говорит?
06.06.2003 18:01:48Uri
Олегу:
А Закон говорит, что должно использоваться сертифицированное средство ЭЦП. Вот когда будет сертифицировано средство ЭЦП, использующей вражеский алгоритм хэширования, вот тогда и используйте его. А CP CSP сертифицировано с реализацией ГОСТ 34.10-94, и там SHA1 не наблюдается в качестве функции хэширования...
06.06.2003 18:07:12Олег
Ну правильно, и как сертифицированное средство CP CSP меняет параметр, если туда кто-то кривыми руками написал SHA1? Да? Функция ведь не выдает ошибки если ей дать вражеский OID
09.06.2003 13:09:42Ильшат Абшарипов
Так дело-то в том, что я не могу шифровать!!! А не то, как КриптоПро меняет алгоритм :)