Ключевое слово в защите информации
ключевое слово
в защите информации
Получить ГОСТ TLS-сертификат для домена (SSL-сертификат)
Добро пожаловать, Гость! Чтобы использовать все возможности Вход. Новые регистрации запрещены.

Уведомление

Icon
Error

4 Страницы123>»
Опции
К последнему сообщению К первому непрочитанному
Offline IvannikovAV  
#1 Оставлено : 14 сентября 2012 г. 13:21:39(UTC)
IvannikovAV

Статус: Новичок

Группы: Участники
Зарегистрирован: 11.05.2012(UTC)
Сообщений: 6
Откуда: Москва

Доброго времени суток!

Столкнулся с необычной проблемой, хочу понять - мои косяки или есть ограничение.

Процедура шифрования на CryptEncryptMessage устойчиво работает при количестве сертификатов до 200, при 250 сертификатах зашифрование отрабатывает без ошибок, но при расшифровывании получаю ошибку "Встречено неверное значение тега ASN1". При количестве сертификатов больше 300 уже при шифровании первый вызов CryptEncryptMessage даёт нулевой размер предполагаемого буфера cbEncrypted и GetLastError даёт ту-же "Встречено неверное значение тега ASN1".

При массиве сертификатов до 200 всё работает устойчиво и нормально расшифровывается.

Пробовал и статический массив и динамический, разницы нет. Границы количества сертификатов для устойчивого шифрования зависят так же от размера входного файла. Изменял от 1 кб до 5 мб, при большом размере входного файла устойчивое шифрование наблюдается до 150 сертификатов в массиве.

При этом на тех-же сертификатах (около 400) КриптоАрм шифрует и моя процедура расшифровывает без ошибок.

Версия КриптоПро 3.6.6497 (ядро 3.6.5359 КС1)

procedure EncryptTest( SourceFileName, CryptFileName : String );
var
Stream : TMemoryStream;
FileStream: TMemoryStream;
Certificate : PCCERT_CONTEXT;
EncParams : CRYPT_ENCRYPT_MESSAGE_PARA;
cbEncrypted : DWORD;
i: Integer;
CertCount: Integer;
aCertName: PWideChar;
RecipientCertArray : TMemoryStream;
EncryptAlgorithm: CRYPT_ALGORITHM_IDENTIFIER;
begin

if not SysUtils.FileExists(SourceFileName) then
begin
ShowMessage('Подлежащий шифрованию файл не обнаружен - ' + SourceFileName);
Exit;
end;

FileStream := TMemoryStream.Create;
try
FileStream.LoadFromFile( SourceFileName );

{Массив сертификатов получателей}
RecipientCertArray := TMemoryStream.Create;
CertCount := 0;

try

Certificate := CertFindCertificateInStore( CertStoreAB,
MY_ENCODING_TYPE,
0,
CERT_FIND_SUBJECT_STR,
StringToPWide('048990000-09'),
nil);

while Certificate <> nil do
begin
RecipientCertArray.SetSize( RecipientCertArray.Size + SizeOf( Pointer ));
TPointerList( RecipientCertArray.Memory^ )[ CertCount ] := PCCERT_CONTEXT( Certificate );
Inc(CertCount);
// if CertCount > 300 then Break;
Certificate := CertEnumCertificatesInStore(CertStoreAB, Certificate);
end;

if Win32Check( Assigned( RecipientCertArray )) then
try
ZeroMemory( @EncParams, SizeOf( CRYPT_ENCRYPT_MESSAGE_PARA ));
EncParams.cbSize := SizeOf( CRYPT_ENCRYPT_MESSAGE_PARA );
EncParams.dwMsgEncodingType := PKCS_7_ASN_ENCODING or X509_ASN_ENCODING;
EncParams.ContentEncryptionAlgorithm.pszObjId := szOID_CP_GOST_R3411;
EncParams.hCryptProv := Prov;

cbEncrypted := 0;

if not CryptEncryptMessage( @EncParams, CertCount, RecipientCertArray.Memory, FileStream.Memory, FileStream.Size, nil, @cbEncrypted ) then
begin
Err('Ощибка шифрования ');
end;

if cbEncrypted > 0 then
begin
Stream := TMemoryStream.Create;
try
Stream.SetSize( cbEncrypted );
CryptEncryptMessage( @EncParams, CertCount, RecipientCertArray.Memory, FileStream.Memory, FileStream.Size, Stream.Memory, @cbEncrypted );
Stream.SaveToFile( CryptFileName );
finally
Stream.Free;
end;
end
else
begin
ShowMessage('При шифровании документа возникла ошибка определения размера зашифрованного документа');
end;
finally
i := 0;
{Высвобождаем ссылки на сертификаты}
while i < CertCount do
begin
Certificate := PCCERT_CONTEXT (TPointerList( RecipientCertArray.Memory^ )[ i ]);
CertFreeCertificateContext( Certificate );
Inc(i)
end;
RecipientCertArray.Free;
end;
finally
end;
finally
FileStream.Free;
end;
end;
Offline Андрей Писарев  
#2 Оставлено : 14 сентября 2012 г. 13:27:15(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 14,190
Мужчина
Российская Федерация

Сказал «Спасибо»: 621 раз
Поблагодарили: 2397 раз в 1886 постах
Цитата:

EncParams.ContentEncryptionAlgorithm.pszObjId := szOID_CP_GOST_R3411;


а почему не szOID_CP_GOST_28147
?


EncParams.hCryptProv := Prov;
вопрос, Prov- глобальная переменная\инициализирована?

Отредактировано пользователем 14 сентября 2012 г. 13:33:47(UTC)  | Причина: Не указана

Техническую поддержку оказываем тут
Наша база знаний
Offline Андрей Писарев  
#3 Оставлено : 14 сентября 2012 г. 13:29:07(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 14,190
Мужчина
Российская Федерация

Сказал «Спасибо»: 621 раз
Поблагодарили: 2397 раз в 1886 постах
Цитата:
CryptEncryptMessage( @EncParams, CertCount, RecipientCertArray.Memory, FileStream.Memory, FileStream.Size, Stream.Memory, @cbEncrypted );

нет проверки ... ?

Отредактировано пользователем 14 сентября 2012 г. 13:34:44(UTC)  | Причина: Не указана

Техническую поддержку оказываем тут
Наша база знаний
Offline IvannikovAV  
#4 Оставлено : 14 сентября 2012 г. 13:52:42(UTC)
IvannikovAV

Статус: Новичок

Группы: Участники
Зарегистрирован: 11.05.2012(UTC)
Сообщений: 6
Откуда: Москва

Prov глобальная, инициализирована, конечно.
Второй проверки не было по причине того, что при первом вызове уже получаю ошибку.

szOID_CP_GOST_28147 даёт ровно тот же результат.
Изначально инициализировалось szOID_RSA_RC4, с этого начал.
Offline VitalyMM  
#5 Оставлено : 16 сентября 2012 г. 14:03:33(UTC)
VitalyMM

Статус: Участник

Группы: Участники
Зарегистрирован: 16.09.2012(UTC)
Сообщений: 25

Здравствуйте. У меня следующая проблема. Необходимо зашифровать файл двумя открытыми сертификатами.
Взял код из Вашего примера. В Delphi из BDS 2006 все прекрасно работает, а вот в RAD Studio XE2,
где мне собственно и нужно, не хочет работать абсолютно.

Header в Wcrypt2 я исправил:

function CryptEncryptMessage(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;

при вызове в RAD Studio XE2:

{1} if not CryptEncryptMessage( @EncParams, CertCount, arCertContext.Memory, FileStream.Memory, FileStream.Size, nil, @cbEncrypted ) then
вываливается ошибка (GetLastError = 2148086027),

а если так
{2} if not CryptEncryptMessage( @EncParams, 1, @Certificate, FileStream.Memory, FileStream.Size, nil, @cbEncrypted ) then
то все нормально, но используется только 1 сертификат, а нужно два...

При этом в Delphi BDS 2006 тот же самый код {1} c 2 сертификатами работает безупречно...

Видимо что-то связано с передачей указателей на сертификаты получателей через через TPointerList, но опыта у меня не хватает, чтобы понять в чем дело.

Заранее благодарен.
Offline Андрей Писарев  
#6 Оставлено : 16 сентября 2012 г. 15:45:26(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 14,190
Мужчина
Российская Федерация

Сказал «Спасибо»: 621 раз
Поблагодарили: 2397 раз в 1886 постах
ошибка "Встречено неверное значение тега ASN1."

(правильно ли читаешь сертификат? + не юникодная vs юникодная версия )
+


Цитата:

{1} if not CryptEncryptMessage( @EncParams, CertCount, arCertContext.Memory, FileStream.Memory, FileStream.Size, nil, @cbEncrypted ) then
вываливается ошибка (GetLastError = 2148086027),


CertCount = 2 ?
а в arCertContext - только один сертификат, так?


array of PCCERT_CONTEXT- ни о чем не говорит?

Отредактировано пользователем 16 сентября 2012 г. 15:52:40(UTC)  | Причина: Не указана

Техническую поддержку оказываем тут
Наша база знаний
Offline VitalyMM  
#7 Оставлено : 17 сентября 2012 г. 3:12:14(UTC)
VitalyMM

Статус: Участник

Группы: Участники
Зарегистрирован: 16.09.2012(UTC)
Сообщений: 25

Спасибо за ответ. Вот вся процедура:
....

if not CryptAcquireContext(@hProv, nil,
'Crypto-Pro GOST R 34.10-2001 Cryptographic Service Provider', 75,
CRYPT_VERIFYCONTEXT) then
begin
InFileName := 'Провайдер не найден';
Result := False;
Exit;
end;

hStoreHandle := CertOpenSystemStore(hProv, 'AddressBook');
enctype := X509_ASN_ENCODING OR PKCS_7_ASN_ENCODING;

FileStream := TMemoryStream.Create;
try
FileStream.LoadFromFile( InFileName );
{Массив сертификатов получателей}
try
arCertContext := TMemoryStream.Create;

MyName := 'Сертификат1';
GetMem(pSignerName,2*Length(MyName)+1);
StringToWideChar(MyName, pSignerName, 2*Length(MyName)+1);
pSignerCert := CertFindCertificateInStore(hStoreHandle, enctype, 0, CERT_FIND_SUBJECT_STR, pSignerName, nil);

if pSignerCert <> nil then begin
arCertContext.SetSize( arCertContext.Size + SizeOf( Pointer ));
TPointerList( arCertContext.Memory^ )[0] := PCCERT_CONTEXT( pSignerCert );
end;

MyName := 'Сертификат2';
GetMem(pSignerName,2*Length(MyName)+1);
StringToWideChar(MyName, pSignerName, 2*Length(MyName)+1);
pSignerCert := CertFindCertificateInStore(hStoreHandle, enctype, 0, CERT_FIND_SUBJECT_STR, pSignerName, nil);

if pSignerCert <> nil then begin
arCertContext.SetSize( arCertContext.Size + SizeOf( Pointer ));
TPointerList( arCertContext.Memory^ )[1] := PCCERT_CONTEXT( pSignerCert );
end;

CertCount := 2;

try
ZeroMemory( @EncParams, SizeOf( CRYPT_ENCRYPT_MESSAGE_PARA ));
EncParams.cbSize := SizeOf( CRYPT_ENCRYPT_MESSAGE_PARA );
EncParams.dwMsgEncodingType := X509_ASN_ENCODING OR PKCS_7_ASN_ENCODING;
EncParams.ContentEncryptionAlgorithm.pszObjId := szOID_CP_GOST_28147;
EncParams.hCryptProv := hProv;

cbEncrypted := 0;

CryptEncryptMessage( @EncParams, CertCount, arCertContext.Memory, FileStream.Memory, FileStream.Size, nil, @cbEncrypted );

if cbEncrypted > 0 then
begin
Stream := TMemoryStream.Create;
try
Stream.SetSize( cbEncrypted );
CryptEncryptMessage( @EncParams, CertCount, arCertContext.Memory, FileStream.Memory, FileStream.Size, Stream.Memory, @cbEncrypted );
Stream.SaveToFile( InFileName + '.enc' );
finally
Stream.Free;
end;
end
else
begin
ShowMessage('При шифровании документа возникла ошибка определения размера зашифрованного документа');
end;
finally
{Высвобождаем ссылки на сертификаты}
for i := 0 to 1 do
CertFreeCertificateContext(TPointerList( arCertContext.Memory^ )[i]);
end;
finally
end;
finally
FileStream.Free;
CertCloseStore(hStoreHandle, 0);
end;

Там 2 сертификата. ЭТОТ ЖЕ код один в один в Delphi BDS 2006 работает безупречно. Проблемы начинаются в RAD Studio XE2... Не знаю почему.


Offline VitalyMM  
#8 Оставлено : 17 сентября 2012 г. 16:53:53(UTC)
VitalyMM

Статус: Участник

Группы: Участники
Зарегистрирован: 16.09.2012(UTC)
Сообщений: 25

Может в RAD Studio XE2 конструкция типа TPointerList( arCertContext.Memory^ )[0] := PCCERT_CONTEXT( pSignerCert ) уже работает по-другому.. Какие-то изменения в стуктуре объекта TList в RAD Studio XE2 точно есть, они об этом сами пишут, но я не понимаю, как теперь правильно изменить указатель на сертификаты получателей, чтобы CryptEncryptMessage их нашел.
Offline Андрей Писарев  
#9 Оставлено : 17 сентября 2012 г. 17:10:32(UTC)
Андрей *

Статус: Сотрудник

Группы: Участники
Зарегистрирован: 26.07.2011(UTC)
Сообщений: 14,190
Мужчина
Российская Федерация

Сказал «Спасибо»: 621 раз
Поблагодарили: 2397 раз в 1886 постах
VitalyMM написал:
Может в RAD Studio XE2 конструкция типа TPointerList( arCertContext.Memory^ )[0] := PCCERT_CONTEXT( pSignerCert ) уже работает по-другому.. Какие-то изменения в стуктуре объекта TList в RAD Studio XE2 точно есть, они об этом сами пишут, но я не понимаю, как теперь правильно изменить указатель на сертификаты получателей, чтобы CryptEncryptMessage их нашел.


а просто динамический массив нельзя уже использовать?
Техническую поддержку оказываем тут
Наша база знаний
Offline VitalyMM  
#10 Оставлено : 17 сентября 2012 г. 21:13:50(UTC)
VitalyMM

Статус: Участник

Группы: Участники
Зарегистрирован: 16.09.2012(UTC)
Сообщений: 25

Может и можно, но во всех аналогичных темах сказано, что в header WinCrypt2

function CryptEncryptMessage(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;

тот самый "array of PCCERT_CONTEXT" для архитектуры Delphi не подходит. И все работающие примеры показаны в том варианте, который пробую я.
Если вернуться к header-у

function CryptEncryptMessage(pEncryptPara :PCRYPT_ENCRYPT_MESSAGE_PARA;
cRecipientCert :DWORD;
rgpRecipientCert :array of PCCERT_CONTEXT; // Вот так было изначально
const pbToBeEncrypted :PBYTE;
cbToBeEncrypted :DWORD;
pbEncryptedBlob :PBYTE;
pcbEncryptedBlob :PDWORD):BOOL ; stdcall;

то как будет выглядеть код добавления сертификатов и ссылка на массив в вызове функции CryptEncryptMessage???

Я перепробовал несколько вариантов с динамическим массивом - результат тот же - (AV).

RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Guest (2)
4 Страницы123>»
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.