01.08.2002 11:51:21Создание сертификата Ответов: 1
Михаил Символоков
Здравствуйте...
Пытаюсь создать сертификат и заверить его тестовым сертификатом (с именем "1") созданным на веб-сайте Крипто-Про. Вызываю следующую функцию:
CreateCertificate (
"E=simvolokov@taxcom.ru,C=RU,S=Moskow,
L=Moskow,O=Taxcom,OU=Test,CN=Michael",//szX509
1, //dwKeyType,
szOID_CP_GOST_R3411, //szSigAlg,
0, //wMonths,
2, //dwUsage,
1, //bCA,
1, //bUseProv,
0, //dwProviderNum,
"MY", //szSubjectStore,
1, //bSubjectUser,
0, //bSelfSigned,
"1", //szIssuerName,
"MY", //szIssuerStore,
1, //bIssuerUser,
0, //bExport,
"", //szCertFile,
"", //szKeyFile,
"", //szPassword,
0, //wBits);
После вызова предлагают сначала вставить в дисковод чистую дикету, а затем подвигать мышкой. Исправно выполняю эти действия... Потом предлагают вставить в дисковод дискету с сертификатом "удостоверяющего центра" для того, что бы подписать вновь созданный сертификат. Вставляю требуемую дискету и после этого получаю сообщение о том, что сертификат успешно создан. Проверяю через MS Explorer: да, действительно новый сертификат появился в списке.
Вопрос вот в чем... Почему при вызове стандартной процедуры Крипто-Про "Сертификаты на носителе" для вновь созданного сертификата появляется сообщение: В контейнере FAT12:000121-12 отсутствует сертификат ключа шифрования.
Что надо сделать для того что бы иметь сертификат подобный тестовому, который создается на сайте Крипто-Про?
 
Ответы:
01.08.2002 14:00:00kure
Дело в том, что добавление сертификата в ключ - это необязательное свойства конкретного провайдера. Задумано оно было в первую очередь для карточных провайдеров.
Реализуется это свойства через две функции:

CryptSetKeyParam, CryptGetKeyParam для каждого конкретного ключа с параметром
KP_CERTIFICATE

В примере property.c приведен текст:
int
KPSet1Cert (HCRYPTKEY hUserKey, PCCERT_CONTEXT pCert)
{
printf ("KPSet1Cert: pCert->dwCertEncodingType =");
if (pCert->dwCertEncodingType&X509_ASN_ENCODING)
printf (" X509_ASN_ENCODING");
if (pCert->dwCertEncodingType&PKCS_7_ASN_ENCODING)
printf (" PKCS_7_ASN_ENCODING");
if (pCert->dwCertEncodingType
& (~(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING))) {
printf (" 0x%x", pCert->dwCertEncodingType
& (~(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING)));
}
printf ("\n");
/* Установить сертификат.*/
if (!CryptSetKeyParam (hUserKey, KP_CERTIFICATE,
pCert->pbCertEncoded, 0)) {
HandleErrorFL ("Error during CryptSetKeyParam.\n");
return 0;
}
return 1;
}

Почему стандартный центр микрософтовый это делает.
Он пользует ActiveX Xenroll, который сделам микрософтом для созадания ключей и запросов и обработки полученных сертификатов. Им пользоваться значительно проще.
Вот самый простой пример создания запроса (в виде html).

<html>

<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<meta http-equiv="Content-Language" content="ru">
<meta name="GENERATOR" content="Microsoft FrontPage 4.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<title>Генерация ключей</title>
</head>

<body>

<table class="PageHeader" width="100%" height="32">
<tr>
<td class="PageHeaderText" bgcolor="#000080" height="28">
<p align="right"><font color="#FFFFFF" face="Tahoma" size="4">Генерация
ключей и запроса на сертификат</font></p>
</td>
</tr>
</table>
<hr>
<p><font face="Tahoma" size="2"><font color="#000080">Пожалуйста,
внимательно заполните поля для
формирования запроса на сертификат. Обязательные
для заполнения поля помечены </font><font color="#FF0000">красным</font><font color="#000080">
цветом. После генерации ключей запрос на
сертификат будет сохранен в файл с именем,
указанным в поле </font></font><font color="red" face="Tahoma" size="2">Имя
файла для сохранения запроса.</font></p>
<p><font color="#000080" face="Tahoma" size="2">Файл с запросом
на сертификат должен быть передан в
Удостоверяющий центр для формирования
сертификата открытого ключа.</font></p>
<hr>
<form name="UIForm" onsubmit="SubmitRequest(); return false;">
<table cellspacing="0" cellpadding="4" width="662">
<tr>
<td valign="center" align="right" class="Form" width="282"><font color="red" face="Tahoma" size="2"><b>Адрес
электронной почты:</b></font></td>
<td width="360"><input name="EMail" style="WIDTH: 300px" maxlength="128" size="20"></td>
</tr>
<tr>
<td valign="center" align="right" class="Form" width="282"><font color="red" face="Tahoma" size="2"><b>Фамилия,
Имя, Отчество (псевдоним):</b></font></td>
<td width="360"><input name="Name" style="WIDTH: 300px" onkeyup="Validate()" maxlength="64" size="20"></td>
</tr>
<tr>
<td valign="center" align="right" class="Form" width="282"><font face="Tahoma" size="2" color="#000080"><b>Организация:</b></font></td>
<td width="360"><input name="Org" style="WIDTH: 300px" onkeyup="Validate()" maxlength="64" size="20"></td>
</tr>
<tr>
<td valign="center" align="right" class="Form" width="282"><font face="Tahoma" size="2" color="#000080"><b>Подразделение:</b></font></td>
<td width="360"><input name="OrgUnit" style="WIDTH: 300px" onkeyup="Validate()" maxlength="64" size="20"></td>
</tr>
<tr>
<td valign="center" align="right" class="Form" width="282"><font color="red" face="Tahoma" size="2"><b>Имя
файла для сохранения запроса:</b></font></td>
<td width="360"><input name="FileName" style="WIDTH: 300px" onkeyup="Validate()" maxlength="64" size="20"></td>
</tr>
</table>
<input type="hidden" name="PKCS10">
<hr>
<p align="right"><input type="submit" value="Продолжить &gt;&gt;" name="Submit" disabled></p>
</form>

<SCRIPT Language="VBScript">

&rsquo;Проверка вводимых значений на лету
Sub Validate()

UIForm.Submit.disabled = true

If (Len(Trim(UIForm.EMail.value))>0) and _
(Len(Trim(UIForm.Name.value))>0) then

If (Len(Trim(UIForm.FileName.value))>0) then
UIForm.Submit.disabled = false
End if

Else
UIForm.Submit.disabled = true
End if
End sub

Function CheckValues()

CheckValues = false

&rsquo;Формат E-Mail
if InStr(UIForm.EMail.value,"@") < 2 or _
InStr(UIForm.EMail.value,"@") = Len(UIForm.EMail.value) then
MsgBox "Неверно указан адрес электронной почты (E-Mail). Неправильный формат."
UIForm.EMail.focus
exit function
end if

CheckValues = true
exit function

End Function

Function SubmitRequest()

&rsquo; check values
If not CheckValues() then
SubmitRequest = false
exit function
End if

&rsquo; make DN string
Dim strDN
strDN = "C=RU"
strDN = "CN=" & UIForm.Name.value
strDN = strDN & ",OU=" & UIForm.OrgUnit.value
strDN = strDN & ",O=" & UIForm.Org.value
strDN = strDN & ",E=" & UIForm.EMail.value
Dim usage

&rsquo;Send request
XEnroll.ProviderType = 2
XEnroll.ProviderName = "Crypto-Pro Cryptographic Service Provider"

XEnroll.KeySpec=1

&rsquo;AT_KEYEXCHANGE=1;
&rsquo;AT_SIGNATURE=2;

usage = "1.3.6.1.5.5.7.3.2"

UIForm.PKCS10.value=XEnroll.createPKCS10(strDN, usage)

a= WriteFileData (UIForm.FileName.value, UIForm.PKCS10.value)

If a<>0 Then
MsgBox Err.Description
End If

&rsquo;RequestForm.submit

End Function


Function WriteFileData(sFileName, sData)
Dim filesystem, file
&rsquo;On Error Resume Next

&rsquo; First, create the FileSystem object
Set filesystem = CreateObject("Scripting.FileSystemObject")
&rsquo; Security may not allow this
If Err.number<>0 Then
WriteFileData=Err.number
Exit Function
End If

&rsquo; check for existing file
Dim bExists
bExists=filesystem.FileExists(sFileName)
If 0<>Err.Number Then
WriteFileData=Err.number
Exit Function
End If
If True=bExists Then
&rsquo;file exists. Overwrite?
If False=myConfirm("The file &rsquo;" & sFileName & "&rsquo; already exists. Overwrite?") Then
WriteFileData=58 &rsquo;File Already Exists
Exit Function
End If
End If

&rsquo; open the specified file
Set file=filesystem.OpenTextFile(sFileName, 2, true) &rsquo;2->ForWriting, true->create
If Err.Number<>0 Then
WriteFileData=Err.number
Exit Function
End If

&rsquo; read the data and stash it into the form
file.Write sData
&rsquo; catch any read errors
If Err.Number<>0 Then
WriteFileData=Err.number
Exit Function
End If

&rsquo; clean up
file.Close
Set file=Nothing
Set filesystem=Nothing
WriteFileData=0
MsgBox "Запрос на сертификат сохранен в файл " & sFileName
End Function

</SCRIPT>

<SCRIPT Language="JavaScript">

function myConfirm(sPrompt) {
return confirm(sPrompt);
}

</SCRIPT>

<object classid="clsid:43F8F289-7A20-11D0-8F06-00C04FC295E1" id="XEnroll" / width="14" height="14">


</body>

</html>
</object>

</body>


А вот пример установки в справочник сертификатов личного сертификата (VBS):

Option Explicit


Dim xenroll

Set xenroll = CreateObject("CEnroll.CEnroll.1")

xenroll.DeleteRequestCert = FALSE
xenroll.WriteCertToCSP = TRUE

xenroll.acceptFilePKCS7 (Wscript.Arguments(0))

If 0=Err.Number Then
Wscript.Echo "Сертификат установлен"
Else
Wscript.Echo "Сертификат не мог быть инсталлирован. Возможно отсутствует запрос на сертификат."
End If