| ||||
| ||||
Здравствуйте! Возникла необходимость создать подчиненный ЦС. Но при установке ЦС Microsoft не получается использовать сертификат подчиненного ЦС, подписанный корневым ЦС. При установке ЦС Microsoft выбираем тип ЦС = «Изолированный подчиненый ЦС». Ставим галку в «Измененные параметры создания пары ключей и сертификата ЦС». При выборе криптопровайдера «CryptoPro-GOST R 34.10-2001» становится доступным поле выбора ключевого контейнера, но сертификат соответствующий этому ключу недоступен. При связке ключа и сертификата непонятно какой тип хранилища для сертификата нужно выбирать. Ведь ключ то «машинный»! Может нужно как то в запросе прописать связь сертификата с ключом? Среда: Windows 2003 Server + CryptoPro CSP 3.0 (CSP +TLS). Генерим ключевой контейнер. В принципе с ключем проблем нет, но на всякий случай привожу код (Borland C++ Builder 6.0): // ------------------------------------------------------ int rv = 0; HCRYPTPROV hCryptProv; HCRYPTKEY hKey; CHAR szUserName[100]; DWORD dwUserNameLen = 100; LPCSTR UserName= “SubCA”; // Инициализируем криптопровайдера rv = CryptAcquireContext( &hCryptProv, UserName, NULL, 75, CRYPT_NEWKEYSET|CRYPT_MACHINE_KEYSET); // Получаем контекст криптопровайдера rv = CryptGetProvParam( hCryptProv, PP_CONTAINER, (BYTE *)szUserName, &dwUserNameLen, 0); // Генерим ключ rv = CryptGenKey( hCryptProv, AT_SIGNATURE, CRYPT_EXPORTABLE, &hKey); // ОСвобождение CryptReleaseContext(hCryptProv,0); // ------------------------------------------------------ Создается ключевой контейнер, через панель управления КриптоПро видимый как «машинный» ключ. Далее создаем запрос: // ------------------------------------------------------ CERT_REQUEST_INFO certReqInfo; PCERT_REQUEST_INFO pRequestInfo; pRequestInfo = &certReqInfo; CERT_NAME_BLOB subjNameBlob; DWORD encNameLen; PBYTE encName; HCRYPTPROV hCryptProv; DWORD pubKeyInfoLen; PCERT_PUBLIC_KEY_INFO pubKeyInfo = NULL; DWORD encCertReqLen; CRYPT_OBJID_BLOB params; CRYPT_ALGORITHM_IDENTIFIER sigAlg; PBYTE signedEncCertReq; DWORD size=0; DWORD encType= PKCS_7_ASN_ENCODING | X509_ASN_ENCODING; … Кодирование субъекта опускаю…. // Расширения PCERT_EXTENSION pExt; CERT_EXTENSION Exts[4]; CERT_EXTENSIONS ReqExts; memset(Exts, 0, sizeof(CERT_EXTENSION)); ReqExts.cExtension = 0; ReqExts.rgExtension = Exts; // Указываем что это сертификат ЦС (CA:TRUE) Exts[0].pszObjId = szOID_BASIC_CONSTRAINTS2; Exts[0].fCritical = 1; CERT_BASIC_CONSTRAINTS2_INFO BasicConstrains; BasicConstrains.fCA = 1; BasicConstrains.fPathLenConstraint = 0; BasicConstrains.dwPathLenConstraint = 0; rv = CryptEncodeObjectEx(encType, szOID_BASIC_CONSTRAINTS2, &BasicConstrains, CRYPT_ENCODE_ALLOC_FLAG, NULL, &Exts[0].Value.pbData, &Exts[0].Value.cbData); ReqExts.cExtension++; // Использование ключа Exts[1].pszObjId = szOID_KEY_USAGE; Exts[1].fCritical = 0; CRYPT_BIT_BLOB KeyUses; BYTE byte[1]; byte[0] = CERT_DIGITAL_SIGNATURE_KEY_USAGE| CERT_KEY_CERT_SIGN_KEY_USAGE| CERT_OFFLINE_CRL_SIGN_KEY_USAGE | CERT_CRL_SIGN_KEY_USAGE; KeyUses.pbData=byte; KeyUses.cbData=1; KeyUses.cUnusedBits=0; rv = CryptEncodeObjectEx(encType, szOID_KEY_USAGE, &KeyUses, CRYPT_ENCODE_ALLOC_FLAG, NULL, &Exts[1].Value.pbData, &Exts[1].Value.cbData); ReqExts.cExtension++; // Версия ЦС (v0.0) Exts[2].pszObjId = szOID_CERTSRV_CA_VERSION; Exts[2].fCritical = 0; BYTE Data[] = {0x02, 0x01, 0x00}; Exts[2].Value.cbData = 3; Exts[2].Value.pbData = Data; ReqExts.cExtension++; // Имя шаблона сертификата (SubCA) Exts[3].pszObjId = szOID_ENROLL_CERTTYPE_EXTENSION; Exts[3].fCritical = 0; BYTE DataS[] = {0x1e, '\n', 0x00, 'S', 0x00, 'u', 0x00, 'b', 0x00, 'C', 0x00, 'A'}; Exts[3].Value.cbData = 12; Exts[3].Value.pbData = DataS; ReqExts.cExtension++; // Добавление расширений в сертификат pRequestInfo->cAttribute = 1; pRequestInfo->rgAttribute = (PCRYPT_ATTRIBUTE)malloc(sizeof(CRYPT_ATTRIBUTE)); pRequestInfo->rgAttribute[0].pszObjId = szOID_CERT_EXTENSIONS; pRequestInfo->rgAttribute[0].cValue = 1; pRequestInfo->rgAttribute[0].rgValue = (PCRYPT_ATTR_BLOB)malloc(sizeof(CRYPT_ATTR_BLOB)); rv = CryptEncodeObjectEx(encType, szOID_CERT_EXTENSIONS, &ReqExts, CRYPT_ENCODE_ALLOC_FLAG, NULL, &pRequestInfo->rgAttribute[0].rgValue[0].pbData, &pRequestInfo->rgAttribute[0].rgValue[0].cbData); // Ну и подписание запроса // Инициализируем криптопровайдера rv = CryptAcquireContext( &hCryptProv, Container, NULL, 75, CRYPT_MACHINE_KEYSET); // Экспорт ключа rv = CryptExportPublicKeyInfo (hCryptProv, AT_SIGNATURE, encType, NULL, &pubKeyInfoLen); pubKeyInfo = (PCERT_PUBLIC_KEY_INFO) malloc (pubKeyInfoLen); rv = CryptExportPublicKeyInfo (hCryptProv, AT_SIGNATURE, encType, pubKeyInfo, &pubKeyInfoLen); certReqInfo.SubjectPublicKeyInfo = *pubKeyInfo; memset(¶ms, 0, sizeof(params)); sigAlg.pszObjId = szOID_CP_GOST_R3411_R3410EL; sigAlg.Parameters = params; rv = CryptSignAndEncodeCertificate (hCryptProv, AT_SIGNATURE, encType, X509_CERT_REQUEST_TO_BE_SIGNED, &certReqInfo, &sigAlg, NULL, NULL, &encCertReqLen); signedEncCertReq = (PBYTE)malloc(encCertReqLen); rv = CryptSignAndEncodeCertificate (hCryptProv, AT_SIGNATURE,//AT_KEYEXCHANGE, encType, X509_CERT_REQUEST_TO_BE_SIGNED, &certReqInfo, &sigAlg, NULL, signedEncCertReq, &encCertReqLen); ofstream outfile(“req.p10”, ios::binary); outfile.write(signedEncCertReq, encCertReqLen); outfile.close(); // ------------------------------------------------------ Отправляем запрос в корневой ЦС (тоже Windows 2003 Server + CryptoPro CSP 3.0 (CSP +TLS)). Сертификат подписывается – все ОК!!! Вот тут начинается засада… При привязке сертификата к ключу используем панель управления КриптоПро. При установке личного сертификата выбираем контейнер машинного ключа “SubCA”, далее следует выбрать тип хранилища – выбираем «ЛИЧНОЕ» (А КАКОЕ НУЖНО?). Для верности устанавливаем сертификат в контейнер закрытого ключа. При просмотре через панель управления КриптоПро сертификат действительно находится в контейнере! Но при установке ЦС ключ доступен, а сертификат нет!!! Может в сертификате что-то не так? Или при связке сертификата и ключа??? | ||||
Ответы: | ||||
| ||||
> При привязке сертификата к ключу используем панель управления КриптоПро. При установке личного сертификата выбираем контейнер машинного ключа “SubCA”, далее следует выбрать тип хранилища – выбираем «ЛИЧНОЕ» (А КАКОЕ НУЖНО?). Тут зависит от деталей. Правильный алгоритм: Панель CSP - Сервис - Установить личный сертификат - указываете файл сертификата, затем перед Обзором контейнеров переставляете галку на контейнеры компьютера, потом выбираете контейнер и далее имя хранилища - Личные. Кроме того, сертификат корневого ЦС должен быть установлен в "Доверенные корневые ЦС" ЛОКАЛЬНОГО КОМПЬЮТЕРА, а сертификат подчинённого ЦС - в "Промежуточные ЦС" ЛОКАЛЬНОГО КОМПЬЮТЕРА. Список отозванных сертификатов корневого ЦС должен быть установлен в "Доверенные корневые ЦС" ЛОКАЛЬНОГО КОМПЬЮТЕРА. > Для верности устанавливаем сертификат в контейнер закрытого ключа. При просмотре через панель управления КриптоПро сертификат действительно находится в контейнере Не имеет значения - сертификат берётся из хранилища, а не из контейнера. > Но при установке ЦС ключ доступен, а сертификат нет!!! Может в сертификате что-то не так? Или при связке сертификата и ключа??? Если сделано всё вышеперечисленное, то дополнительно рекомендуется поменять пароль на контейнер “SubCA” на пустой на время установки MS CA. Потом можно будет поставить. | ||||
| ||||
Василий, большое спасибо! Всё заработало! Тема закрыта. | ||||