11.03.2002 11:48:17xenroll и КриптоПро Ответов: 2
Алексей
подскажите пожалуйста пример использования
компоненты xenroll для запроса , получения
сертификатов открытых ключей для работы
с функциями КриптоПро CPEncrypt CPDecrypt.
Насколько я понял, данная компонента при
генерации запроса сертификата автоматически генерит ключевые пары в обход CPGetUserKey.
Откуда их можно извлечь после работы этой компоненты? И вообще корректный алгоритм
использования рез-тов работы xenroll
в функция CPEncrypt и CPDecrypt и в функциях подписи?
 
Ответы:
12.03.2002 12:50:20kure
Совсем не так.
Xenroll является COM интерфейсом над некоторыми функциями CryptoAPI, которые используются для генерации ключей, создания запроса (PKCS#10) и обработки сертификатов (помещения их в Store).
Он не может использовать никаких других функций для генерации ключей, кроме CPGenKey от выбранного (указанного) криптопровайдера.

Примеры использования функций CryptEncrypt (CryptDecrypt) находятся в тестовом ПО http://www.cryptopro.ru/test/sample.zip

Пример использования Xenroll для генерации ключей и установки сертификатов - центр сертификации Microsoft (ASP страницы \\winnt\system32\certsrv), страницы VeriSign (https://digitalid.verisign.com/client/class1MS.htm)

Простенький пример для создания запроса и сохранения в файл:

<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">

'Проверка вводимых значений на лету
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

'Формат 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()

' check values
If not CheckValues() then
SubmitRequest = false
exit function
End if

' 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

'Send request
XEnroll.ProviderType = 2
XEnroll.ProviderName = "Crypto-Pro Cryptographic Service Provider"

XEnroll.KeySpec=1

'AT_KEYEXCHANGE=1;
'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

'RequestForm.submit

End Function


Function WriteFileData(sFileName, sData)
Dim filesystem, file
'On Error Resume Next

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

' 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
'file exists. Overwrite?
If False=myConfirm("The file '" & sFileName & "' already exists. Overwrite?") Then
WriteFileData=58 'File Already Exists
Exit Function
End If
End If

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

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

' 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
Const ForReading = 1, ForWriting = 2


Dim xenroll
Dim PKCS7, ret

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


LoadFile Wscript.Arguments(0), PKCS7


xenroll.DeleteRequestCert = FALSE
xenroll.WriteCertToCSP = TRUE

Wscript.Echo xenroll.MyStoreName
Wscript.Echo xenroll.MyStoreFlags
'Wscript.Echo xenroll.MyStoreType

Wscript.Echo PKCS7

xenroll.CAStoreName = "My"
xenroll.InstallPKCS7 (PKCS7)

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



Sub LoadFile (FileName, Buffer)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")

If Not fso.FileExists(FileName) Then
MsgBox "Error: " & FileName & " file not found."
Exit Sub
End If

Dim ts
Set ts = fso.OpenTextFile(FileName, ForReading)
Buffer = ts.ReadAll
End Sub
13.03.2002 12:39:16Алексей
Перевел Ваш пример на С++
При createPKCS10 получаю ошибку 80090019
- ключевой набор не установлен

BSTR bstrreq=NULL;
ICEnroll * pEnroll = NULL;

// variable for return value
HRESULT hr;

// Initialize COM.
hr = CoInitializeEx( NULL, COINIT_APARTMENTTHREADED );

// Check status.
if ( FAILED( hr ) )
{
sprintf(str1,"Failed CoInitializeEx - [%x]", hr);
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
goto error;
}

// Create an instance of the object.
hr = CoCreateInstance( CLSID_CEnroll,
NULL,
CLSCTX_INPROC_SERVER,
IID_ICEnroll,
(void **)&pEnroll);

// Check status.
if ( FAILED( hr ) )
{
sprintf(str1,"Failed CoCreateInstance - pEnroll [%x]", hr);
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
goto error;
}
else
{
// Successfully instantiated object.
sprintf(str1,"Obtained pointer to Enrollment interface");
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
// Use object as needed.
// ...
}

hr = pEnroll->put_ProviderName((wchar_t*)"Crypto-Pro Cryptographic Service Provider");
if (FAILED( hr ))
{
sprintf(str1,"Failed put_ProviderName - %x", hr );
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
goto error;
}
else
{
sprintf(str1,"ProviderName set");
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
}

hr = pEnroll->put_KeySpec( AT_KEYEXCHANGE );
if (FAILED( hr ))
{
sprintf(str1,"Failed put_KeySpec - %x", hr );
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
goto error;
}
else
{
sprintf(str1,"KeySpec set to %d", AT_KEYEXCHANGE );
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
}

hr = pEnroll->put_ProviderType(2);
if (FAILED(hr))
{
sprintf(str1,"Failed put_ProviderType - %x", hr);
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
goto error;
}
else
{
sprintf(str1,"ProviderType set");
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
}

strcpy(str1,"CN=Your Name,OU=Your Unit,O=Your Org,L=Redmond,S=Washington,C=US");
hr=pEnroll->createPKCS10((wchar_t*)str1,(wchar_t*)"1.3.6.1.5.5.7.3.2",&bstrreq);
if (FAILED(hr))
{
sprintf(str1,"Failed createPKCS10 - %x", hr);
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
goto error;
}
else
{
// Success.
sprintf(str1,"Successfully created file containing PKCS10");
MessageBox(NULL,str1,"qq",MB_OK|MB_TASKMODAL);
}

error:

// Done processing.
// Clean up resources.
if ( NULL != pEnroll )
pEnroll->Release();

// Free COM resources.
CoUninitialize();

//return hr;