Статус: Активный участник
Группы: Участники
Зарегистрирован: 19.02.2008(UTC) Сообщений: 66 Откуда: Москва
|
Создаю массив строк, заполняю строками, например, "строка1", "строка2", шифрую, расшифровываю закрытым ключем, записываю в другой массив. Получаю в нем "строка1", "строка1строка1" :( Есть подозрение, что Delphi (или я!) что-то путает с указателями. Может, параметры CryptEncryptMessage не правильные? На сообщения обработчиков ошибок прошу внимания не обращать. Код функции: Код:
Типы и переменные:
type
TStringArray = array of string;
var
strs, strs2, strs3: TStringArray;
Вызов:
SetLength(strs, 2);
SetLength(strs2, 2);
SetLength(strs3, 2);
strs[0] := 'test';
strs[1] := 'dfgdsfg';
strs2 := EncryptArrayWithKey(ContName, '12345678', strs, True);
strs3 := DecryptArrayWithKey(ContName, '12345678', strs2, True);
ShowMessage('a: ' + strs3[0] + ' ||||||| ' + strs3[1]);
Код функции:
function EncryptArrayWithKey(ContName: string; ContPassword: string; Txts: TStringArray; MakeBase64: Boolean = False): TStringArray;
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;
i: Integer;
FreeMemValue: Integer;
ByteText: PByte;
begin
if (ContName = pEmptyStr) then Exit;
SetLength(Result, Length(Txts));
cc := TCryptContext.Create(PAnsiChar(ContName), CP_GR3410_94_PROV_A, PROV_GOST_94_DH, []);
if ContPassword <> pEmptyStr then
SetCurContainerPassword(cc.Provider, ContPassword);
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;
SetLength(CertBytes, datalen);
if not CryptGetKeyParam(hXChagngeKey, KP_CERTIFICATE, PByte(PChar(CertBytes)), @datalen, 0) then
begin
MessageDlg('Error installing certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
pCertContext := CertCreateCertificateContext(X509_ASN_ENCODING, PByte(PChar(CertBytes)), datalen);
//
{if GetPublicKeyString(cc.Provider, pCertContext, pb, pbSize) = sEmptyStr then begin
MessageDlg('Error installing certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
if not CryptImportKey(cc.Provider, pb, pbSize, hXChagngeKey, CRYPT_EXPORTABLE, @hPubKey) then begin
MessageDlg('Error installing certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;}
//*********** Initialize the algorithm identifier structure. ******
EncryptAlgSize := SizeOf(EncryptAlgorithm);
ZeroMemory(@EncryptAlgorithm, EncryptAlgSize);
EncryptAlgorithm.pszObjId := szOID_CP_GOST_28147;
//********** Initialize the CRYPT_ENCRYPT_MESSAGE_PARA structure. ***
EncryptParamsSize := SizeOf(EncryptParams);
ZeroMemory(@EncryptParams, EncryptParamsSize);
EncryptParams.cbSize := EncryptParamsSize;
EncryptParams.dwMsgEncodingType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
EncryptParams.hCryptProv := cc.Provider;
EncryptParams.ContentEncryptionAlgorithm := EncryptAlgorithm;
//*********************************************
// Пробуем получить длину будущего сообщения
//*********************************************
arCertContext := TMemoryStream.Create;
arCertContext.SetSize(SizeOf(pCertContext));
TPointerList(arCertContext.Memory^)[0] := pCertContext;
// pCertificateContext := PCCERT_CONTEXT( pICertificate.Header );
for i := 0 to Length(Txts) - 1 do
begin
a := PAnsiChar(Txts[i]);
cbContent := Length(a);
if not CryptEncryptMessage(@EncryptParams, 1, arCertContext.Memory, PByte(a), cbContent, nil, @cbEncryptedBlob) then
begin
MessageDlg('Error installing certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
GetMem(pbEncryptedBlob, cbEncryptedBlob);
FreeMemValue := cbEncryptedBlob;
if not CryptEncryptMessage(@EncryptParams, 1, arCertContext.Memory, PByte(a), cbContent, pbEncryptedBlob, @cbEncryptedBlob) then
begin
MessageDlg('Error installing certificate in container: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
Result[i] := CopyStr2(pbEncryptedBlob, cbEncryptedBlob);
if MakeBase64 then
Result[i] := EncodeStr(Result[i]);
//
FreeMem(pbEncryptedBlob, FreeMemValue);
pbEncryptedBlob := nil;
cbEncryptedBlob := 0;
FreeMemValue := 0;
a := nil;
end;
arCertContext.Free;
//
CryptDestroyKey(hXChagngeKey);
CertFreeCertificateContext(pCertContext);
CryptReleaseContext(Prov, 0);
cc.Free;
end;
function DecryptArrayWithKey(ContName: string; ContPassword: string; Txts: TStringArray; FromBase64: Boolean = False): TStringArray;
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;
i: Integer;
DecryptParams: CRYPT_DECRYPT_MESSAGE_PARA;
DecryptParamsSize: DWORD;
FileContent: string; //PChar;
FileContentSize: Cardinal;
DecryptSize: DWORD;
DecryptSize2: DWORD;
DecryptedBlob: PByte;
Certs: HCERTSTORE;
PrivateKeyInfo: CERT_KEY_CONTEXT;
hMemStore: HCERTSTORE;
pCertContext2: PCCERT_CONTEXT;
begin
SetLength(Result, Length(Txts));
cc := TCryptContext.Create(PAnsiChar(ContName), CP_GR3410_94_PROV_A, PROV_GOST_94_DH, []);
SetCurContainerPassword(cc.Provider, ContPassword);
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;}
//Don't work with CryptDecryptMessage
// Trying with CertStore
//Certs := CertOpenSystemStore(cc.Provider, 'MY');
hMemStore := CertOpenStore(CERT_STORE_PROV_MEMORY, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, cc.Provider, 0, nil);
if hMemStore = nil then
begin
MessageDlg('Error in CertOpenStore: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
if not CertAddCertificateContextToStore(hMemStore, pCertContext, CERT_STORE_ADD_REPLACE_EXISTING, pCertContext2) then
begin
MessageDlg('Error in CertAddCertificateContextToStore: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
pCertContext := nil;
pCertContext := CertFindCertificateInStore(hMemStore {Certs}, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, CERT_FIND_ANY, 0, nil, pCertContext);
while (pCertContext <> nil) do
begin
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;
//
pCertContext := CertFindCertificateInStore(hMemStore {Certs}, PKCS_7_ASN_ENCODING or X509_ASN_ENCODING, CERT_FIND_ANY, 0, nil, pCertContext);
end;
DecryptParamsSize := SizeOf(DecryptParams);
ZeroMemory(@DecryptParams, DecryptParamsSize);
DecryptParams.cbSize := DecryptParamsSize;
DecryptParams.dwMsgAndCertEncodingType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
DecryptParams.cCertStore := 1;
DecryptParams.rghCertStore := @hMemStore; //@Certs; {@pCertContext;}
for i := 0 to Length(Txts) - 1 do
begin
if FromBase64 then
FileContent := DecodeStr(Txts[i]) //LoadFromFile('c:\1.txt'); //PChar(LoadFromFile('c:\1.txt'));
else
FileContent := Txts[i];
FileContentSize := Length(FileContent); //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);
DecryptSize2 := DecryptSize; // После первого вызова получается размер чуть больше, чем реально будет записано. Поэтому, возможна утечка памяти на разницу между размерами. Поэтому запоминаем максимальный размер для дальнейшей очистки
if not CryptDecryptMessage(@DecryptParams, PByte(FileContent), FileContentSize, DecryptedBlob, @DecryptSize, nil) then
begin
MessageDlg('Error decrypting information: ' + IntToStr(GetLastError), mtError, [mbOK], 0);
Exit;
end;
Result[i] := CopyStr(DecryptedBlob, DecryptSize); // PByte -> String
FreeMem(DecryptedBlob, DecryptSize2);
{DeleteFile('c:\2.txt');
SaveToFile('c:\2.txt', CopyStr(DecryptedBlob, DecryptSize));}
end;
arCertContext.Free;
//
CertCloseStore(hMemStore, CERT_CLOSE_STORE_CHECK_FLAG {CERT_CLOSE_STORE_FORCE_FLAG});
CryptDestroyKey(hXChagngeKey);
CertFreeCertificateContext(pCertContext);
CryptReleaseContext(Prov, 0);
cc.Free;
end;
|