26.05.2006 16:26:13CryptSignMessage и CryptVerifyMessageSignature Ответов: 0
Василий
На 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;