| ||||
| ||||
Непонятная ошибка. Функция 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; | ||||
Ответы: | ||||
| ||||
кстати на счет SignParams.HashAlgorithm.pszObjId := szOID_CP_GOST_R3411_R3410; Чего то я где то читал что CP CSP на этот параметр нещадно забивает - ставит правильный в любом случае. Меня бы это очень устроило - поставил бы SHA1 и моя бы функция не задумывалась бы об алгоритме сертификата которым подписываем. И тем не менее - что будет если в нашей подписи будет вражеский алгоритм хэширования? Что нам закон об ЭЦП говорит? | ||||
| ||||
Олегу: А Закон говорит, что должно использоваться сертифицированное средство ЭЦП. Вот когда будет сертифицировано средство ЭЦП, использующей вражеский алгоритм хэширования, вот тогда и используйте его. А CP CSP сертифицировано с реализацией ГОСТ 34.10-94, и там SHA1 не наблюдается в качестве функции хэширования... | ||||
| ||||
Ну правильно, и как сертифицированное средство CP CSP меняет параметр, если туда кто-то кривыми руками написал SHA1? Да? Функция ведь не выдает ошибки если ей дать вражеский OID | ||||
| ||||
Так дело-то в том, что я не могу шифровать!!! А не то, как КриптоПро меняет алгоритм :) | ||||