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

Уведомление

Icon
Error

Опции
К последнему сообщению К первому непрочитанному
Offline Ильшат Абшарипов  
#1 Оставлено : 7 марта 2008 г. 18:56:14(UTC)
Ильшат Абшарипов

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

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

Добрый день.

Опишу проблему. Клиенту был выписан сертификат (Key Usage: Signature). Далее этот сертификат был установлен через браузер. После чего при открытии этого сертификата в консоли mmc можно было видеть, что у него есть личный ключ, и этот сертификат можно было без вопросов экспортировать в файл.
Была написана программка для экспорта закрытого ключа сертификата. Ключи были выгружены в файл, а контейнер был удален при помощи утилиты администрирования КриптоПро (в Панели Инструментов).
Далее была написана еще одна программа для импорта этих файлов (сертификата и закрытого ключа) в систему. Сертификат добавляется, ключ привязывается, но теперь при открытии сертификата при экспорте его в файл выдается окно с запросом на выбор ключевого носителя с неудобоваримым названием. Я так понимаю, что требуется выбрать носитель, в котором были первоначально сгенерированы ключи? Возможно ли обойти данный запрос?
Далее. При попытке подписать какие-либо данные данным сертификатом выдается ошибка NTE_KEYSET_NOT_DEF. Как задать контейнер для ключа сертификата?

Как делался экспорт закрытого ключа
Код:

// Открываем хранилище
hStore := CertOpenStore(CERT_STORE_PROV_SYSTEM, cnt_ENCODING_TYPE, 0, CERT_SYSTEM_STORE_CURRENT_USER, 'MY');

// Берем нужный нам сертификат
pCert := CrpGetCertContext(hStore, IssuerName, CertSerial);

// Берем провайдера относящегося к сертификату
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, nil, ProvInfoSize);
pProvInfo := PCRYPT_KEY_PROV_INFO(AllocMem(ProvInfoSize));
CertGetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, pProvInfo, ProvInfoSize);
CryptAcquireContext(hProv, PAnsiChar(WideCharToString(pProvInfo.pwszContainerName)), nil, pProvInfo.dwProvType, 0);

// получаем ключ, который будем экспортировать
CryptGetUserKey(hProv, AT_SIGNATURE, hUserKey);

// на основании пароля создаем ключ обмена, на котором будет экспортироваться искомая ключевая пара
CryptCreateHash(hProv, CALG_GR3411, 0, 0, hHash);

CryptHashData(hHash, PByte(KeyPassword), StrLen(KeyPassword), 0);

CryptDeriveKey(hProv, CALG_G28147, hHash, CRYPT_EXPORTABLE, hSessionKey);

// экспортируем ключи
algid_export := CALG_PRO_EXPORT;
CryptSetKeyParam(hSessionKey, KP_ALGID, @algid_export, 0);

CryptExportKey(hUserKey, hSessionKey, PRIVATEKEYBLOB, 0, nil, KeyBufLen);
KeyBuf := AllocMem(KeyBufLen);
CryptExportKey(hUserKey, hSessionKey, PRIVATEKEYBLOB, 0, KeyBuf, KeyBufLen);

// Далее чистим ресурсы
// Всё


Как проводился импорт сертификата и ключа

Код:

// получим контекст сертификата
pCert := CertCreateCertificateContext(X509_ASN_ENCODING, CertData, CertDataLen);

// открываем хранилище сертификатов MY (личное)
hStore := CertOpenStore(CERT_STORE_PROV_SYSTEM, cnt_ENCODING_TYPE, 0, CERT_SYSTEM_STORE_CURRENT_USER, 'MY');

// пробуем получить контейнер в реестре с именем mycontainer
if not CryptAcquireContext(hProv, 'mycontainer', nil, 75, CRYPT_SILENT) then
	// если такого контейнера нет, то создаем его
	if not CryptAcquireContext(hProv, 'mycontainer', nil, 75, CRYPT_NEWKEYSET) then
		raise Exception.Create('Container error');

// зададим пароль на доступ к контейнеру
Buf := '12345678';
CryptSetProvParam(hProv, PP_SIGNATURE_PIN, PByte(Buf), 0);

// создаем ключ, на котором был зашифрована ключевая пара
CryptCreateHash(hProv, CALG_GR3411, 0, 0, hHash);
CryptHashData(hHash, PByte(KeyDataPassword), StrLen(KeyDataPassword), 0);
CryptDeriveKey(hProv, CALG_G28147, hHash, CRYPT_EXPORTABLE, hSessionKey);

// импортируем ключ в контейнер
algid_export := CALG_PRO_EXPORT;
CryptSetKeyParam(hSessionKey, KP_ALGID, @algid_export, 0);

CryptImportKey(hProv, KeyData, KeyDataLen, hSessionKey, 0, hKey);

// заполняем имя контейнера
provInfo.pwszContainerName := 'mycontainer';

// заполняем имя провайдера
provInfo.pwszProvName := CP_DEF_PROV; // 'Crypto-Pro Cryptographic Service Provider'

// заполняем тип провайдера
provInfo.dwProvType := PROV_GOST_DH; // 75

// устанавливаем привязку ключей к сертификату
provInfo.dwFlags := CERT_SET_KEY_PROV_HANDLE_PROP_ID;
provInfo.cProvParam := 0;
provInfo.rgProvParam := nil;
provInfo.dwKeySpec := AT_SIGNATURE;
CertSetCertificateContextProperty(pCert, CERT_KEY_PROV_INFO_PROP_ID, 0, @provInfo);

// заносим сертификат в хранилище
CertAddCertificateContextToStore(hStore, pCert, CERT_STORE_ADD_ALWAYS, nil);

// очищаем ресурсы
// всё
Offline Максим Коллегин  
#2 Оставлено : 7 марта 2008 г. 21:25:14(UTC)
Максим Коллегин

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

Группы: Администраторы
Зарегистрирован: 12.12.2007(UTC)
Сообщений: 6,092
Мужчина
Откуда: КРИПТО-ПРО

Сказал «Спасибо»: 19 раз
Поблагодарили: 613 раз в 546 постах
Цитата:
// заполняем имя контейнера
provInfo.pwszContainerName := 'mycontainer';

// заполняем имя провайдера
provInfo.pwszProvName := CP_DEF_PROV; // 'Crypto-Pro Cryptographic Service Provider'
это юникодные строки?
Знания в базе знаний, поддержка в техподдержке
RSS Лента  Atom Лента
Пользователи, просматривающие эту тему
Быстрый переход  
Вы не можете создавать новые темы в этом форуме.
Вы не можете отвечать в этом форуме.
Вы не можете удалять Ваши сообщения в этом форуме.
Вы не можете редактировать Ваши сообщения в этом форуме.
Вы не можете создавать опросы в этом форуме.
Вы не можете голосовать в этом форуме.