Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Access Violation при вызове CryptSignAndEncryptMessage


DmitrySukach ©   (2006-07-27 14:58:00) 

Подскажите, что я делаю неправильно?
Вот полностью код после получения pCertContext:
const
CERT_ENCODING_TYPE = X509_ASN_ENCODING or PKCS_7_ASN_ENCODING;
var
pCertContext: PCCERT_CONTEXT;
SignPara: CRYPT_SIGN_MESSAGE_PARA;
EncryptPara: CRYPT_ENCRYPT_MESSAGE_PARA;
pbSignedAndEncryptedBlob: PBYTE;
dwKeySpec: DWORD;
hCryptProv: HCRYPTPROV;
bToBeSignedAndEncrypted: array[0..1] of BYTE;
cbToBeSignedAndEncrypted: DWORD;
cbSignedAndEncryptedBlob: DWORD;
begin
CryptAcquireCertificatePrivateKey(
pCertContext,
0,
nil,
@hCryptProv,
@dwKeySpec,
nil);

FillChar(SignPara, SizeOf(CRYPT_SIGN_MESSAGE_PARA), 0);
SignPara.cbSize := SizeOf(CRYPT_SIGN_MESSAGE_PARA);
SignPara.dwMsgEncodingType := CERT_ENCODING_TYPE;
SignPara.pSigningCert := pCertContext;
SignPara.HashAlgorithm.pszObjId := szOID_RSA_MD2;
SignPara.cMsgCert := 1;
SignPara.rgpMsgCert := @pCertContext;

FillChar(EncryptPara, SizeOf(CRYPT_SIGN_MESSAGE_PARA), 0);
EncryptPara.cbSize := SizeOf(CRYPT_ENCRYPT_MESSAGE_PARA);
EncryptPara.dwMsgEncodingType := CERT_ENCODING_TYPE;
EncryptPara.ContentEncryptionAlgorithm.pszObjId := szOID_RSA_RC4;
EncryptPara.ContentEncryptionAlgorithm.Parameters.cbData := 0;
EncryptPara.pvEncryptionAuxInfo := nil;
EncryptPara.dwFlags := 0;
EncryptPara.dwInnerContentType := 0;

cbToBeSignedAndEncrypted := 1;
bToBeSignedAndEncrypted[0] := 33;
bToBeSignedAndEncrypted[1] := 44;
cbSignedAndEncryptedBlob := 0;
pbSignedAndEncryptedBlob := nil;

CryptSignAndEncryptMessage(
@SignPara,
@EncryptPara,
1,
pCertContext,
@bToBeSignedAndEncrypted,
cbToBeSignedAndEncrypted,
nil,
@cbSignedAndEncryptedBlob);
...

На этом вызове и вылетает.


Reindeer Moss Eater   (2006-07-27 18:00:00) [1]

procedure SignMessage(const AFileIn, AFileOut: string);
var
SignParams     : CRYPT_SIGN_MESSAGE_PARA;
pAuthorCert    : PCCERT_CONTEXT;
hStoreHandle   : HCERTSTORE;
hProv             : HCRYPTPROV;
bDetached      : boolean;
dwToBeSigned   : DWORD;
pbToBeSigned   : PBYTE;
dwSigned       : DWORD;
pbSigned       : PBYTE;
pbDummyArray   : Pointer;
cbDummyElem    : PByte;
cbDummyArray   : Pointer;
begin
bDetached := False;
get_file_data(AFileIn,dwToBeSigned,pbToBeSigned);
pbDummyArray   := @pbToBeSigned;
cbDummyArray   := @dwToBeSigned;
hStoreHandle   := CertOpenSystemStore(hProv,'MY');
if hStoreHandle = nil then Exit;
pAuthorCert := GetCertificateByTypeAndName('ИмяВладельца',hStoreHandle,AT_SIGNATURE); //пользовательская ф-ция, возвращающая сертификат по имени владельца
if pAuthorCert = nil then Exit;
ZeroMemory(@SignParams,SizeOf(CRYPT_SIGN_MESSAGE_PARA));
SignParams.cbSize                   := SizeOf(CRYPT_SIGN_MESSAGE_PARA);
SignParams.dwMsgEncodingType        := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
SignParams.pSigningCert             := pAuthorCert;
SignParams.HashAlgorithm.pszObjId   := szOID_CP_GOST_R3411;// szOID_RSA_MD5;
SignParams.HashAlgorithm.Parameters.cbData := 0;
SignParams.cMsgCert                 := 0;
SignParams.rgpMsgCert               := nil;
SignParams.cAuthAttr                := 0;
SignParams.dwInnerContentType       := 0;
SignParams.cMsgCrl                  := 0;
SignParams.cUnauthAttr              := 0;
SignParams.dwFlags                  := 0;
if not CryptSignMessage(@SignParams,bDetached,1,pbDummyArray,cbDummyArray,nil,@dwSigned ) then Exit;
GetMem(pbSigned,dwSigned);
if CryptSignMessage(@SignParams,bDetached,1,pbDummyArray,cbDummyArray,pbSigned,@dwS igned) then
 SaveDataToFile(AFileOut,pbSigned^,dwSigned);
FreeMem(pbToBeSigned,dwToBeSigned);
FreeMem(pbSigned,dwSigned);
CertFreeCertificateContext(pAuthorCert);
CertCloseStore(hStoreHandle,0);
end;


DmitrySukach   (2006-07-27 17:17:00) [2]

А рабютающий пример с CryptSignMessageесть?


Reindeer Moss Eater   (2006-07-27 16:14:00) [3]

>Теперь вызов возвращает False и GetLastError даёт E_INVALIDARG...

Остается побороть заполнение параметров.
Примера с CryptSignAndEncryptMessage нет.
Только по отдельности.


DmitrySukach   (2006-07-27 15:56:00) [4]

Reindeer Moss Eater,
Вы не могли написать какой-нибудь работающий пример с CryptSignAndEncryptMessage?


DmitrySukach   (2006-07-27 15:46:00) [5]

Заменил прототип. Теперь вызов возвращает False и GetLastError даёт E_INVALIDARG...


Reindeer Moss Eater   (2006-07-27 15:33:00) [6]

Вот моя переделка одной из деклараций

function CryptEncryptMessageMy(pEncryptPara          : PCRYPT_ENCRYPT_MESSAGE_PARA;
                              cRecipientCert        : DWORD;
                              rgpRecipientCert      : PCCERT_CONTEXT; //array of PCCERT_CONTEXT;
                              const pbToBeEncrypted : PBYTE;
                              cbToBeEncrypted       : DWORD;
                              pbEncryptedBlob       : PBYTE;
                              pcbEncryptedBlob      : PDWORD) : BOOL; stdcall;

То есть я использую просто скалярный параметр PCCERT_CONTEXT.
Если получателей больше одного, я "руками" распределяю память под несколько указателей и руками же рассовываю туда все PCCERT_CONTEXT.
А в качестве параметра идет первый из них.


Reindeer Moss Eater   (2006-07-27 15:28:00) [7]

Про декларацию я уже говорил. Это одна из причин.
На джедаях выложена кривая трансяция Wincrypt2.h
Исходные параметры типа таких PCCERT_CONTEXT rgpRecipientCert[] везде заменены открытыми массивами Delphi. Но там совсем другая физическая организация.

Дальше надо искать ошибку в заполнении структур.


DmitrySukach   (2006-07-27 15:27:00) [8]

На Visual C++ это работает:

СryptAcquireCertificatePrivateKey(
       pSignerCertContext,
       0,
       NULL,
       &hCryptProv,
       &dwKeySpec,
       NULL);

   SignPara.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
   SignPara.dwMsgEncodingType = MY_ENCODING_TYPE;
   SignPara.pSigningCert = pSignerCertContext ;
   SignPara.HashAlgorithm.pszObjId = szOID_RSA_MD2;
   SignPara.HashAlgorithm.Parameters.cbData = 0;
   SignPara.pvHashAuxInfo = NULL;
   SignPara.cMsgCert = 1;
   SignPara.rgpMsgCert = &pSignerCertContext ;
   SignPara.cMsgCrl = 0;
   SignPara.rgpMsgCrl = NULL;
   SignPara.cAuthAttr = 0;
   SignPara.rgAuthAttr = NULL;
   SignPara.cUnauthAttr = 0;
   SignPara.rgUnauthAttr = NULL;
   SignPara.dwFlags = 0;
   SignPara.dwInnerContentType = 0;

   EncryptPara.cbSize = sizeof(CRYPT_ENCRYPT_MESSAGE_PARA);
   EncryptPara.dwMsgEncodingType = MY_ENCODING_TYPE;
   EncryptPara.hCryptProv = 0;
   EncryptPara.ContentEncryptionAlgorithm.pszObjId = szOID_RSA_RC4;
   EncryptPara.ContentEncryptionAlgorithm.Parameters.cbData = 0;
   EncryptPara.pvEncryptionAuxInfo = NULL;
   EncryptPara.dwFlags = 0;
   EncryptPara.dwInnerContentType = 0;

   cRecipientCert = 1;
   rgpRecipientCert[0] = pSignerCertContext;
   *pcbSignedAndEncryptedBlob = 0;
   pbSignedAndEncryptedBlob = NULL;

   CryptSignAndEncryptMessage(
       &SignPara,
       &EncryptPara,
       cRecipientCert,
       rgpRecipientCert,
       pbToBeSignedAndEncrypted,
       cbToBeSignedAndEncrypted,
       NULL,
       pcbSignedAndEncryptedBlob)


DmitrySukach   (2006-07-27 15:24:00) [9]

Я делал и так:

 cRecipientCert: DWORD;
 rgpRecipientCert: array[0..4] of PCCERT_CONTEXT;

 cRecipientCert := 1;
 rgpRecipientCert[0] := pCertContext;

 CryptSignAndEncryptMessage(
     @SignPara,
     @EncryptPara,
     cRecipientCert,
     rgpRecipientCert,
     @bToBeSignedAndEncrypted,
     cbToBeSignedAndEncrypted,
     nil,
     @cbSignedAndEncryptedBlob);

Тот же результат...


Reindeer Moss Eater   (2006-07-27 15:20:00) [10]

Засада вот здесь :

rgpRecipientCert : array of PCCERT_CONTEXT;


DmitrySukach   (2006-07-27 15:19:00) [11]

function CryptSignAndEncryptMessage(pSignPara :PCRYPT_SIGN_MESSAGE_PARA;
                                   pEncryptPara :PCRYPT_ENCRYPT_MESSAGE_PARA;
                                   cRecipientCert :DWORD;
                                   rgpRecipientCert :array of PCCERT_CONTEXT;
                             const pbToBeSignedAndEncrypted :PBYTE;
                                   cbToBeSignedAndEncrypted :DWORD;
                                   pbSignedAndEncryptedBlob :PBYTE;
                                   pcbSignedAndEncryptedBlob :PDWORD
                                   ):BOOL ; stdcall;


DmitrySukach   (2006-07-27 15:18:00) [12]

Я же написал: "Вот полностью код после получения pCertContext". Сертификат я получил нормально:

 pCertContext := CertFindCertificateInStore(hStore, CERT_ENCODING_TYPE, 0,
   CERT_FIND_ANY, nil, nil);

 CertNameToStr(CERT_ENCODING_TYPE, @(pCertCtx^.pCertInfo^.Subject),
   CERT_SIMPLE_NAME_STR, szName, MAXBUFF);
 ShowMessage('Subject: ' + szName);

Это всё работает, субъект показывает.


Reindeer Moss Eater   (2006-07-27 15:17:00) [13]

Нарисуй сюда свой прототип CryptSignAndEncryptMessage


Сергей М.   (2006-07-27 15:13:00) [14]


> что я делаю неправильно?


Как минимум одно - не выделяешь память под CCERT_CONTEXT


Наверх

Титульная страница Поиск, карта сайта Написать письмо