14.04.2005 8:37:24Праблема CryptSignMessage Ответов: 1
Дмитрий
Уважаемые специ, у меня при обращении к CryptSignMessage выпадает программа с ошибкой Access violation.... read adress 00000001. подскажите что тут не так.
текст проги ниже

var
param:CRYPT_SIGN_MESSAGE_PARA;
pUserCert :PCCERT_CONTEXT; { /* User certificate to be used*/}
ret:integer;
mem_tbs :Pbyte;
mem_len :dword;
MessageSizeArray :array [0..1] of dword;
MessageArray :array [0..1] of pbyte;
signed_len :DWORD;
signed_mem :PBYTE;
pCryptKeyProvInfo :CRYPT_KEY_PROV_INFO ;
cbData :DWORD;

cablob: array [0..1] of CRYPT_ATTR_BLOB;
ca : array [0..1] of CRYPT_ATTRIBUTE;
pbAuth :PBYTE;
cbAuth : DWORD;
fileTime :TFILETIME;
systemTime :TTIME;

{--}
OID:Pchar;
subj: PWideChar;
hCertStore :pointer;

res1,bOol:boolean;
infile,outfile:file;
nameString: PChar;
begin
hCertStore:=CertOpenSystemStore(0,’MY’);
nameString:=’2508033345-250801001.250800844850@25.atkas-2.ru’;
GetMem (subj, 2 * length (nameString) + 1);
StringToWideChar (nameString, subj, 2 * length (nameString) + 1);
pUserCert:= CertFindCertificateInStore (hCertStore, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, 0,
CERT_FIND_SUBJECT_STR, subj, nil);



if (pUserCert^.pCertInfo^.SubjectPublicKeyInfo.Algorithm.pszObjId<> szOID_CP_GOST_R3410) then
ShowMessage(&rsquo;Ошибка алгаритма шифрования&rsquo;);



freeMem(subj);

CertCloseStore(hCertStore, 0);
OID:= szOID_CP_GOST_R3411;
{===============================================================================}
{ ==================================================================}
OpenDlg.Title := &rsquo;Укажите исходный файл для подписи&rsquo;;
if OpenDlg.Execute then AssignFile(infile, OpenDlg.FileName)
else exit;
reset(infile,1);
mem_len:=FileSize(infile);

GetMem(mem_tbs,mem_len);
BlockRead(infile,mem_tbs^,mem_len);
{ /*--------------------------------------------------------------------*/

/* Установим параметры*/

/* Обязательно ныжно обнулить все поля структуры. */
/* Иначе это может привести к access violation в функциях CryptoAPI*/
/* В примере из MSDN это отсутствует*/}
{ GetMem(param, sizeof(CRYPT_SIGN_MESSAGE_PARA));}
FillChar(param, sizeof(CRYPT_SIGN_MESSAGE_PARA),0);

param.cbSize:= sizeof(CRYPT_SIGN_MESSAGE_PARA);
param.dwMsgEncodingType:= TYPE_DER;
param.pSigningCert:= pUserCert;

param.HashAlgorithm.pszObjId:=szOID_CP_GOST_R3411_R3410;
param.HashAlgorithm.Parameters.cbData := 0;
param.HashAlgorithm.Parameters.pbData := nil;
param.pvHashAuxInfo := nil; {/* не используется*/}
{!!!!!!!!!!!!!!!!!}
param.cMsgCert := 0; { /* не вклачаем сертификат отправителя*/}
param.rgpMsgCert := nil;
param.cAuthAttr := 0;
param.dwInnerContentType := 0;
param.cMsgCrl := 0;
param.cUnauthAttr := 0;

{ /*---------------------------------------------------------------------------------
Определим системное время и добавим его в список аутентифицируемых (подписанных)
атрибутов PKCS#7 сообщения с идентификатором szOID_RSA_signingTime.
---------------------------------------------------------------------------------*/}
systemTime:=Date;
fileTime:=DateTimeToFileTime(date);


{ /* Определим требуемую длину для хранения времени*/}
if not CryptEncodeObject(TYPE_DER,
szOID_RSA_signingTime,
@fileTime,
nil,
@cbAuth) then
ShowMessage(&rsquo;Cannot encode object&rsquo;);

GetMem(pbAuth,cbAuth);

{ /* Кодирование времени в атрибут типа szOID_RSA_signingTime */}
if not CryptEncodeObject(TYPE_DER,
szOID_RSA_signingTime,
@fileTime,
pbAuth,
@cbAuth) then
ShowMessage(&rsquo;"Cannot encode object"&rsquo;);

cablob[0].cbData := cbAuth;
cablob[0].pbData := pbAuth;


ca[0].pszObjId := szOID_RSA_signingTime;
ca[0].cValue := 1;
ca[0].rgValue := @cablob;

param.cAuthAttr := 1;
param.rgAuthAttr := @ca;


{ /*---------------------------------------------------------------------------------
dwFlags
Normally zero. If the encoded output is to be a CMSG_SIGNED inner content
of an outer cryptographic message such as a CMSG_ENVELOPED message,
the CRYPT_MESSAGE_BARE_CONTENT_OUT_FLAG must be set.
If it is not set, the message will be encoded as an inner content type of CMSG_DATA.
With Windows 2000, CRYPT_MESSAGE_ENCAPSULATED_CONTENT_OUT_FLAG can be set
to encapsulate non-data inner content into an OCTET STRING.
Also, CRYPT_MESSAGE_KEYID_SINGER_FLAG can be set to identify signers
by their Key Identifier and not their Issuer and Serial Number.
---------------------------------------------------------------------------------*/}
param.dwFlags :=0 ;

MessageArray[0] := mem_tbs;
MessageSizeArray[0] := mem_len;


{ /* Возможен вариант использования функции CryptSignMessage в двухпроходной схеме*/
/* с передачей вместо исходных данных нуля для определения длины подписанных данных*/
/* (см. раздел Возвращение данных неопределенной длины в Руководстве программиста).*/
/* В этом случае функция CryptSignMessage производит инициализацию провайдера, соответствующего сертификату и */
/* подпись данных для определения длины, что приводит к необходимости двойной загрузки ключа.*/
/**/
/* Для того чтобы этого избежать приложение может заранее зарезервировать определенное */
/* количество памяти, достаточное для создания подписанного сообщения.*/

/*--------------------------------------------------------------------*/
/* Определение длины подписанного сообщения*/}
{ CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);}



RES1:=false;
if not CryptSignMessage(
@param,
res1,
1,
MessageArray,
MessageSizeArray,
nil,
@signed_len) then
ShowMessage(&rsquo;Signature creation error&rsquo;);;
 
Ответы:
14.04.2005 13:01:02Юрий
Перепишите данную функцию на C/C++ :) Возможно, пока будете переписывать ошибка и исправиться :)