![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
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