Статус: Активный участник
Группы: Участники
Зарегистрирован: 19.02.2008(UTC) Сообщений: 66 Откуда: Москва
|
Зашифровал с помощью CryptEncryptMessage, без ошибок (были проблемы как в http://www.cryptopro.ru/...o/forum/view.asp?q=2188, но решились как там же). При расшифровке с помощью CryptDecryptMessage при втором вызове (непосредственно расшифровка) выскакивает ошибка Access Violation в библиотеке crypt32.dll (чтение по адресу 00000047); Пробывал в CRYPT_DECRYPT_MESSAGE_PARA вместо указания хранилища давать контектс сертификата с заполненным CERT_KEY_CONTEXT_PROP_ID, ругалась на библиотеку ntdll.dll (запись по адресу ABABABBB). Вот код (активен код с указанием CertStore для CryptDecryptMessage, код с указанием контекста сертификата закомменчен): Код:
var
Prov: HCRYPTPROV;
hKey: HCRYPTKEY;
hXChagngeKey: HCRYPTKEY;
//
keyProvInfo: CRYPT_KEY_PROV_INFO;
cc: TCryptContext;
//
encCertLen: DWORD;
encCert: PByte;
context: PCCERT_CONTEXT;
encType: DWORD;
DecodedCert: string;
store: HCERTSTORE;
n: PCCERT_CONTEXT;
//
CertInCont: TCert;
CertBytes: string;
pCertContext: PCCERT_CONTEXT;
datalen: Integer;
subjnamestring: pchar;
//
pb: PByte;
pbSize: Cardinal;
hPubKey: HCRYPTKEY;
//
EncryptAlgSize: DWORD;
EncryptParamsSize: DWORD;
EncryptAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
EncryptParams: CRYPT_ENCRYPT_MESSAGE_PARA;
RecipientCertArray: array of PCCERT_CONTEXT;
cbContent: DWORD;
cbEncryptedBlob: DWORD;
pbEncryptedBlob: PByte;
pbContent: PByte;
Dummy: PByte;
a: PChar;
arCertContext: TMemoryStream;
DT: TTime;
i: Integer;
DecryptParams: CRYPT_DECRYPT_MESSAGE_PARA;
DecryptParamsSize: DWORD;
FileContent: PChar;
FileContentSize: Cardinal;
DecryptSize: DWORD;
DecryptedBlob: PByte;
Certs: HCERTSTORE;
PrivateKeyInfo: CERT_KEY_CONTEXT;
const
ContName = 'Prism';
begin
cc := TCryptContext.Create(PAnsiChar(ContName), CP_GR3410_94_PROV_A, PROV_GOST_94_DH, []);
SetCurContainerPassword(cc.Provider, '12345678');
CryptGetUserKey(cc.Provider, AT_KEYEXCHANGE, @hXChagngeKey);
datalen := 0;
if not CryptGetKeyParam(hXChagngeKey, KP_CERTIFICATE, nil, @datalen, 0) then
begin
MessageDlg('Error installing certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
exit;
end;
//Don't work with CryptDecryptMessage
// SetLength(CertBytes, datalen);
//
// if not CryptGetKeyParam(hXChagngeKey, KP_CERTIFICATE, PByte(PChar(CertBytes)), @datalen, 0) then
// begin
// MessageDlg('Error of certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
// Exit;
// end;
//
// pCertContext := CertCreateCertificateContext(PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, PByte(PChar(CertBytes)), datalen);
//
// PrivateKeyInfo.cbSize := SizeOf(PrivateKeyInfo);
// PrivateKeyInfo.hCryptProv := cc.Provider;
// PrivateKeyInfo.dwKeySpec := AT_KEYEXCHANGE;
// if not CertSetCertificateContextProperty(pCertContext, CERT_KEY_CONTEXT_PROP_ID, 0, @PrivateKeyInfo) then
// begin
// MessageDlg('Error in CERT_KEY_CONTEXT_PROP_ID: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
// Exit;
// end;
//
// datalen := 0;
// if not CertGetCertificateContextProperty(pCertContext, CERT_KEY_CONTEXT_PROP_ID, nil, @datalen) then
// begin
// MessageDlg('Error in CertGetCertificateContextProperty: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
// Exit;
// end;
// Trying with CertStore
Certs := CertOpenSystemStore(0{cc.Provider}, 'MY');
DecryptParamsSize := SizeOf(DecryptParams);
ZeroMemory(@DecryptParams, DecryptParamsSize);
DecryptParams.cbSize := DecryptParamsSize;
DecryptParams.dwMsgAndCertEncodingType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
DecryptParams.cCertStore := 1;
DecryptParams.rghCertStore := Certs;//@pCertContext;
FileContent := PChar(LoadFromFile('c:\1.txt'));
FileContentSize := GetFileSize('c:\1.txt');
if not CryptDecryptMessage(@DecryptParams, PByte(FileContent), FileContentSize, nil, @DecryptSize, nil) then
begin
MessageDlg('Error decrypting information: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
GetMem(DecryptedBlob, DecryptSize);
if not CryptDecryptMessage(@DecryptParams, PByte(FileContent), FileContentSize, DecryptedBlob, @DecryptSize, nil) then
begin
MessageDlg('Error decrypting information: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
memLog.Text := CopyStr(DecryptedBlob, DecryptSize); // PByte -> String
arCertContext.Free;
FreeMem(DecryptedBlob, DecryptSize);
//
CryptDestroyKey(hXChagngeKey);
CertFreeCertificateContext(pCertContext);
CryptReleaseContext(Prov, 0);
cc.Free;
end;
Важные обстоятельства, возможно, являющиеся причиной ошибки: 1. Шифрую и расшифровываю на одном ПК. То есть, использую один сертификат и расшифровываю, давая его же контекст (так как есть связь с секретным ключем); 2. Шифрую файл размером 99000 байт, размер зашифрованного файла - 99 393. ВАЖНО! При первом вызове CryptDecryptMessage в переменную для хранения размера расшифрованного файла записывается 99006 (байт). Где может быть ошибка?
|