06.07.2005 19:20:26СКЗИ Крипто-Про CSP 2.0 Ответов: 1
Золотарёв Роман Григорьевич
Добрый день,

У наших разработчиков ПО возникли сложности с использованием СКЗИ Крипто-Про CSP 2.0. Помогите, пожалуйста.

Проблема возникает при следующей последовательности действий:
- GetLocalTime()
- CryptAcquireContext(), CryptReleaseContext()

- SetLocalTime() - перевод времени
- CryptAcquireContext(), CryptReleaseContext()

- SetLocalTime() - перевод времени
- CryptAcquireContext() - возвращает ошибку

Инициализация криптопровайдера по имени и типу:
CryptAcquireContext(&hProv, 0, prov_name, prov_type, CRYPT_VERIFYCONTEXT)

При изменении времени дважды, CryptAcquireContext() возвращает ошибку:
NTE_KEYSET_ENTRY_BAD
(0x8009001AL)
MessageText:
Keyset as registered is invalid.
The pszContainer key container was found but is corrupt.

С другими криптопровайдерами такой ситуации не возникает.
Как обойти эту ситуацию?

Пример кода:
/////////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <stdio.h>
#include <conio.h>

void find_prov();

//_________________________________________________

int main()
{

SYSTEMTIME t;
GetLocalTime(&t);
find_prov();

t.wHour-=2;
SetLocalTime(&t);
find_prov();

t.wHour+=2;
SetLocalTime(&t);
find_prov(); // ошибка при CryptAcquireContext()

printf("Press any key ...\n");
while(!kbhit());

return 0;

}

//_________________________________________________

void find_prov()
{
printf("find_prov\n");

DWORD dwIndex = 0;

for(;;dwIndex++) //перебор провайдеров
{
DWORD prov_type;

char *prov_name = NULL;
DWORD prov_name_len = 0;

//запросить длину буфера для имени провайдера
//получить тип провайдера
int rc=CryptEnumProviders(dwIndex, NULL, 0, &prov_type, NULL, &prov_name_len);
if(!rc)
{
printf("end_enum_prov\n");
printf("________________________________________________________________\n");
return; //перебрали всех провайдеров
}

prov_name = new char[prov_name_len];
//имя прова
rc=CryptEnumProviders(dwIndex, NULL, 0, &prov_type, prov_name, &prov_name_len);
if(!rc)
{
delete prov_name;
continue;
}

printf("type:%d\t%s\n",prov_type,prov_name);

//по имени и типу
HCRYPTPROV hProv;
rc=CryptAcquireContext(&hProv, 0, prov_name, prov_type, CRYPT_VERIFYCONTEXT);
delete prov_name;
if(!rc)
{
DWORD e = GetLastError();
printf("CryptAcquireContext() CODE:%0x\n",e);

char err_message[1000];
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) err_message, sizeof(err_message), NULL );
printf("%s\n",err_message);
printf("-----------------------\n");

continue;
}
else
CryptReleaseContext(hProv, 0);

} //end перебор провайдеров

return;
}

//_________________________________________________
 
Ответы:
07.07.2005 19:37:23Serge3leo
Что касается синхронизации часов, то для Solaris/FreeBSD/Linux систем рекомендуется использовать ntp_adjtime()/adjtime()/adjtimex(), а для Windows SetSystemTimeAdjustment().