| ||||
| ||||
На MSDN есть пример программки на C: Signing a Message and Verifying a Message Signature. Воспроизвёл его на Delphi c небольшими изменениями. Проблема: CryptSignMessage работает, а СryptVerifyMessageSignature определяет правильно размер исходного сообщения, но при получении исходного сообщения выдаёт false. GetLastError возвращает С0000005 в HEX. В чем дело? Подпись: var hStoreHandle : HCERTSTORE; strMessage : string; pbMessage : PByte; cbMessage : Dword; pSignerCert : PCCERT_CONTEXT; SigParams : CRYPT_SIGN_MESSAGE_PARA; MessageArray : array of PByte; MessageSizeArray : array of DWORD; pvPara: PChar; pvFindPara : PWideChar; err: string; begin strMessage := 'CryptoAPI is a good way to handle security'; GetMem(pbMessage,Length(strMessage)+1); StrPCopy(PChar(pbMessage),strMessage); cbMessage := StrLen(PChar(pbMessage)) + 1; SetLength(MessageArray,1); MessageArray[0] := pbMessage; SetLength(MessageSizeArray,1); MessageSizeArray[0] := cbMessage; GetMem(pvPara,Length(CERT_STORE_NAME)+1); StrPCopy(pvPara,CERT_STORE_NAME); hStoreHandle := CertOpenSystemStore(0,CERT_STORE_NAME); if hStoreHandle = nil then begin err := getErrorString(GetLastError); exit; end; //Получаем сертификат GetMem(pvFindPara,2*Length(SIGNER_NAME)+1); StringToWideChar(SIGNER_NAME,pvFindPara,2*Length(SIGNER_NAME)+1); pSignerCert := CertFindCertificateInStore(hStoreHandle, MY_TYPE, 0, CERT_FIND_SUBJECT_STR, pvFindPara, nil); FreeMem(pvFindPara); if pSignerCert = nil then begin err := getErrorString(GetLastError); exit; end; if not CertCloseStore(hStoreHandle,0) then begin err := getErrorString(GetLastError); exit; end; //Инициализируем структуру подписи SigParams.cbSize := sizeof(CRYPT_SIGN_MESSAGE_PARA); SigParams.dwMsgEncodingType := MY_TYPE; SigParams.pSigningCert := pSignerCert; SigParams.HashAlgorithm.pszObjId := szOID_CP_GOST_R3411; SigParams.HashAlgorithm.Parameters.cbData := 0; SigParams.cMsgCert := 1; SigParams.rgpMsgCert := @pSignerCert; SigParams.cAuthAttr := 0; SigParams.dwInnerContentType := 0; SigParams.cMsgCrl := 0; SigParams.cUnauthAttr := 0; SigParams.dwFlags := 0; SigParams.pvHashAuxInfo := nil; SigParams.rgAuthAttr := nil; //Получаем размер подписи if not CryptSignMessageMy(@SigParams, false, 1, MessageArray, MessageSizeArray, nil, @cbSignedMessageBlob) then begin err := getErrorString(GetLastError); exit; end; //Подписываем GetMem(pbSignedMessageBlob,cbSignedMessageBlob); if not CryptSignMessageMy(@SigParams, false, 1, MessageArray, MessageSizeArray, pbSignedMessageBlob, @cbSignedMessageBlob) then begin err := getErrorString(GetLastError); exit; end; CertFreeCertificateContext(pSignerCert); FreeMem(pbMessage); Проверка: var VerifyParams : CRYPT_VERIFY_MESSAGE_PARA; cbDecodedMessageBlob : DWORD; pbDecodedMessageBlob : PBYTE; DecodedMessage : PChar; err: string; begin VerifyParams.cbSize := sizeof(CRYPT_VERIFY_MESSAGE_PARA); VerifyParams.dwMsgAndCertEncodingType := MY_TYPE; VerifyParams.hCryptProv := hProv; VerifyParams.pfnGetSignerCertificate := nil; VerifyParams.pvGetArg := nil; //Определяем размер выходного сообщения if not CryptVerifyMessageSignatureMy(@VerifyParams, 0, pbSignedMessageBlob, cbSignedMessageBlob, nil, @cbDecodedMessageBlob, nil) then begin err := getErrorString(GetLastError); exit; end; if not CryptVerifyMessageSignatureMy(@VerifyParams, 0, pbSignedMessageBlob, cbSignedMessageBlob, pbDecodedMessageBlob, @cbDecodedMessageBlob, nil) then begin err := getErrorString(GetLastError); exit; end; |