<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:pingback="http://madskills.com/public/xml/rss/module/pingback/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:dc="http://purl.org/dc/elements/1.1/" version="2.0">
  <channel>
    <title>Vadims Podans's blog - PowerShell | CryptoAPI</title>
    <link>http://www.sysadmins.lv/</link>
    <description>PowerShell powered</description>
    <image>
      <url>http://www.sysadmins.lv/images/imgusr/bilde.jpg</url>
      <title>Vadims Podans's blog - PowerShell | CryptoAPI</title>
      <link>http://www.sysadmins.lv/</link>
    </image>
    <language>en-us</language>
    <copyright>Vadims Podāns</copyright>
    <lastBuildDate>Sat, 03 Jul 2010 19:48:17 GMT</lastBuildDate>
    <generator>newtelligence dasBlog 2.3.9074.18820</generator>
    <managingEditor>vpodans@sysadmins.lv</managingEditor>
    <webMaster>vpodans@sysadmins.lv</webMaster>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=2c2eef6f-34ae-42cb-8ded-318e96f63f8c</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,2c2eef6f-34ae-42cb-8ded-318e96f63f8c.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,2c2eef6f-34ae-42cb-8ded-318e96f63f8c.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=2c2eef6f-34ae-42cb-8ded-318e96f63f8c</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Программная обработка запросов сертификатов в папке Pending Requests</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,2c2eef6f-34ae-42cb-8ded-318e96f63f8c.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,2c2eef6f-34ae-42cb-8ded-318e96f63f8c.aspx</link>
      <pubDate>Sat, 03 Jul 2010 19:48:17 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Как известно, когда запрос попадает в папку Pending Requests, администратор CA должен что-то с ним явно сделать — или одобрить или отклонить. Это можно сделать при помощи оснастки CetSrv.msc или при помощи PowerShell. Ещё можно через certutil, но речь сегодня не о нём. Если вспомнить предыдущие посты посвящённые &lt;a href="http://www.sysadmins.lv/CategoryView,category,PowerShellCryptoAPI.aspx"&gt;CryptoAPI и PowerShell&lt;/a&gt;, можно вспомнить какие-то основные принципы. Как обычно, мы будем использовать интерфейс &lt;a href="http://msdn.microsoft.com/en-us/library/aa383234(VS.85).aspx" target="_blank"&gt;ICertAdmin2&lt;/a&gt;. Для аппрува соответствующих запросов необходимо воспользоваться методом &lt;img src="http://i.msdn.microsoft.com/Global/Images/clear.gif" /&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa383250(VS.85).aspx" target="_blank"&gt;ResubmitRequest()&lt;/a&gt;. Как вы видите, метод принимает 2 аргумента:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;code&gt;HRESULT ResubmitRequest(        &lt;br /&gt;&lt;strong&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/code&gt;&lt;code&gt;&lt;strong&gt;[in] const BSTR strConfig,          &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &lt;/strong&gt;&lt;/code&gt;&lt;code&gt;&lt;strong&gt;[in] LONG RequestId,          &lt;br /&gt;&lt;/strong&gt;&amp;#160;&amp;#160;&amp;#160; [out, retval] LONG *pDisposition         &lt;br /&gt;);&lt;/code&gt;&amp;#160;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;это конфигурационная строка CA вида: CAComputerName\CAName и номер запроса. И в ответ метод возвращает результат выполнения операции. Вот как это можно аккуратно сделать в PowerShell:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;Issue-PendingRequest&lt;/span&gt;&lt;span style="color: #000000"&gt; {
[CmdletBinding()]
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;param&lt;/span&gt;&lt;span style="color: #000000"&gt;(
        [Parameter(Mandatory &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;, ValueFomPipeline &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;)]
        [&lt;font color="#008080"&gt;string&lt;/font&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$CAConfig&lt;/span&gt;&lt;span style="color: #000000"&gt;,
        [Parameter(Mandatory &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;)]
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$RequestID&lt;/span&gt;&lt;span style="color: #000000"&gt;
    )
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;CertificateAuthority.Admin&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;catch&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Write-Warning&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Unable to instantiate ICertAdmin2 object!&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;span style="color: #000000"&gt; {
        &lt;/span&gt;&lt;span style="color: #800080"&gt;$status&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;switch&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt;.ResubmitRequest(&lt;/span&gt;&lt;span style="color: #800080"&gt;$CAConfig&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800080"&gt;$RequestID&lt;/span&gt;&lt;span style="color: #000000"&gt;)) {
            &lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The request was not completed.&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
            &lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The request failed.&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
            &lt;/span&gt;&lt;span style="color: #000000"&gt;2&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The request was denied&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
            &lt;/span&gt;&lt;span style="color: #000000"&gt;3&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The certificate was issued.&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
            &lt;/span&gt;&lt;span style="color: #000000"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The certificate was issued separately.&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
            &lt;/span&gt;&lt;span style="color: #000000"&gt;5&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The request was taken under submission.&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
            &lt;/span&gt;&lt;span style="color: #000000"&gt;6&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The certificate is revoked.&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
        }
    }
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;catch&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Write-Host&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Operation status for the request '$RequestID': $ststus&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Для отклонения запроса, следует воспользоваться методом &lt;a href="http://msdn.microsoft.com/en-us/library/aa383236(VS.85).aspx" target="_blank"&gt;DenyRequest()&lt;/a&gt;. Как и метод ResubmitRequest тоже принимает всего 2 аргумента, но кроме ошибок ничего не возвращает:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;code&gt;HRESULT DenyRequest( 
      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [in] const BSTR strConfig, 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [in] Long RequestId 

      &lt;br /&gt;);&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;И код будет очень похож на предыдущий:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;Deny-PendingRequest&lt;/span&gt;&lt;span style="color: #000000"&gt; {
[CmdletBinding()]
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;param&lt;/span&gt;&lt;span style="color: #000000"&gt;(
        [Parameter(Mandatory &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;, ValueFomPipeline &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;)]
        [&lt;font color="#008080"&gt;string&lt;/font&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$CAConfig&lt;/span&gt;&lt;span style="color: #000000"&gt;,
        [Parameter(Mandatory &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;)]
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$RequestID&lt;/span&gt;&lt;span style="color: #000000"&gt;
    )
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;CertificateAuthority.Admin&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;catch&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Write-Warning&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Unable to instantiate ICertAdmin2 object!&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;try&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt;.DenyRequest(&lt;/span&gt;&lt;span style="color: #800080"&gt;$CAConfig&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800080"&gt;$RequestID&lt;/span&gt;&lt;span style="color: #000000"&gt;)}
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;catch&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Write-Host&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Successfully denied request '$RequestID'&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;вот так легко можно программным способом управлять реквестами из папки Pending Requests без графических оснасток или certutil. Что касается certutil, я не уверен, что он сможет заапрувить или отклонить реквест на удалённом CA. У него есть параметр –config, но я не уверен, что он работает в данном случае. Плюс, когда я выложу в общий доступ свой PS модуль для PKI, эта операция будет ещё проще. Вам не придётся вручную набивать конфигурационную строку, а просто воспользоваться командой Get-CertificationAuthority.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=2c2eef6f-34ae-42cb-8ded-318e96f63f8c"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,2c2eef6f-34ae-42cb-8ded-318e96f63f8c.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / CryptoAPI</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=e4b733ed-3f9f-46a4-8698-819263b36f65</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,e4b733ed-3f9f-46a4-8698-819263b36f65.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,e4b733ed-3f9f-46a4-8698-819263b36f65.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=e4b733ed-3f9f-46a4-8698-819263b36f65</wfw:commentRss>
      <title>Осторожно, баг!</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,e4b733ed-3f9f-46a4-8698-819263b36f65.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,e4b733ed-3f9f-46a4-8698-819263b36f65.aspx</link>
      <pubDate>Sat, 01 May 2010 22:46:05 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;MSDN и Microsoft меня однажды доканает и я уйду проповедовать &lt;strike&gt;православный&lt;/strike&gt;богомерзкий линукс.&lt;/p&gt;  &lt;p&gt;А дело в том, что одна моя задумка с треском проваливалась из-за непонятного и тупого бага в интерфейсе &lt;a href="http://msdn.microsoft.com/en-us/library/aa383295(VS.85).aspx" target="_blank"&gt;ICertEncodeAltName&lt;/a&gt;. Это CryptoAPI интерфейс, который позволяет кодировать строковые значения для расширения Subject Alternative Name в ASN.1 DER encoded строку. На возню с ним я потратил почти неделю (чуть меньше, наверное) и только сегодня я смог найти все ответы. Хотя я это должен был сделать много раньше, но дико тупил на ровном месте. Итак, давайте посмотрим, что из себя представляет этот баг.&lt;/p&gt;  &lt;p&gt;Для начала я покажу как собирается этот интерфейс:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;span style="color: #800080"&gt;$san&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;CertificateAuthority.EncodeAltName&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Далее, его надо инициализировать методом &lt;a href="http://msdn.microsoft.com/en-us/library/aa383627(VS.85).aspx" target="_blank"&gt;Reset()&lt;/a&gt; и в качестве аргумента метода указать размер объекта. Т.е. количество элементов, которые должны содержаться в расширении Subject Alternative Name. Если только один элемент, то и указываете число 1:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$san&lt;/span&gt;&lt;span style="color: #000000"&gt;.Reset(&lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;и теперь можно в него заряжать данные методом &lt;a href="http://msdn.microsoft.com/en-us/library/aa383657(VS.85).aspx" target="_blank"&gt;SetNameEntry()&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$san&lt;/span&gt;&lt;span style="color: #000000"&gt;.SetNameEntry(&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0x3&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Custom-Name&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Где 0 — индекс массива, в который надо записать строку, 0x3 — тип строки. В данном случае это DNS и последний аргумент указывает само значение строки. Полный список типов можно получить вот здесь: &lt;a title="http://msdn.microsoft.com/en-us/library/aa374981(VS.85).aspx" href="http://msdn.microsoft.com/en-us/library/aa374981(VS.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/aa374981(VS.85).aspx&lt;/a&gt;. Только учтите, что реально типы начинаются не с нуля (как по ссылке), а с единицы. т.е. 0x3 в нашем случае это DNS (2+1).&lt;/p&gt;

&lt;p&gt;После того как мы загнали туда данные, их можно кодировать:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$san&lt;/span&gt;&lt;span style="color: #000000"&gt;.Encode()&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;И давайте посмотрим, что у нас получилось:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $san = New-Object -ComObject CertificateAuthority.EncodeAltName
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $san.Reset(1)
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $san.SetNameEntry(0,0x3,&amp;quot;Custom-Name&amp;quot;)
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $str = $san.Encode()
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $str
???????&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;выглядит прикольно. Но на самом деле это строка из символов, которые описаны не одним, а двумя байтами:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $str.ToCharArray() | %{[int][char]$_}
3376
2946
30019
29811
28015
20013
28001&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Чтобы убедиться, что в каждом символе по 2 байта, мы преобразуем эти числа в их шестнадцатиричное (hex) представление:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $str.ToCharArray() | %{&amp;quot;{0:X4}&amp;quot; -f [int][char]$_}
0D30
0B82
7543
7473
6D6F
4E2D
6D61&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;видите, в каждом символе по 2 байта и все они записаны в little-endian последовательности. Т.е. первый байт находится справа, а не слева, как обычно. Давайте соберём эти байты в последовательную строку, переставив байты местами в каждой строке:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;30 0D 82 0B 43 75 73 74 6F 6D 2D 4E 61 6D&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;И что же означают эти циферки-букавки? А означают они следующее:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;30 (48) — тип кодировки. 30 или 48 (в десятичном представлении) означает Constructed encoding. &lt;/li&gt;

  &lt;li&gt;0D (13) — длину строки начиная со следующего байта. Остаточная длина должна быть 13 байт. Но моя математика говорит, что дальше не 13, а только 12 байт. &lt;/li&gt;

  &lt;li&gt;82 (130) — тип закодированной строки. 130 означает DNS. 80 (128) — OtherName, 81 (129) — RFC822Name и т.д. &lt;/li&gt;

  &lt;li&gt;0B (11) — размер строки начиная со следующего байта. Остаточная длина должна быть 11 байт. Но моя математика говорит, что их там не 11, а только 10 байт. &lt;/li&gt;

  &lt;li&gt;Остальные байты — сама строка, только в hex'е. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Куда-то пропал один очень важный байт, из-за чего сервер CA начинал доставлять шлакоблоки при виде такой строки. В принципе, мы можем посмотреть, что у нас потерялось по дороге:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $str1 = &amp;quot;43 75 73 74 6F 6D 2D 4E 61 6D&amp;quot;.split(&amp;quot; &amp;quot;)
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $str1 | %{$a += invoke-expression [char]0x$_}
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $a
Custom-Nam&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Последний символ куда-то провалился. Нет его больше. Т.е. размер вычислен правильно, просто не хватает одного байта. Причём, если попробовать что-то другое, попроще, интерфейс возвращает правильный размер и все байты. Я не знаю точно, в каких условиях этот баг проявляется, но уже очевидно, что если в строке присутствует дефис, уже начинается бяка.&lt;/p&gt;

&lt;p&gt;Что можно сделать? Вариантов куча. Как вы видите ASN.1 DER кодировка достаточно простая, её можно сделать самому. Либо использовать православные интерфейсы CertEnroll — &lt;a href="http://msdn.microsoft.com/en-us/library/aa378081(VS.85).aspx" target="_blank"&gt;IX509ExtensionAlternativeNames&lt;/a&gt;. На первый взгляд там багов не обнаружено &lt;img alt=":)" src="/smilies/happy.gif"&gt;. Примеры использования данных интерфейсов можно посмотреть (а заодно и почитать) в моём буржуйском бложике: &lt;a title="How to add FQDN to HP iLO request" href="http://en-us.sysadmins.lv/Lists/Posts/Post.aspx?ID=11"&gt;How to add FQDN to HP iLO request&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;На сегодня всё. Спокночи.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=e4b733ed-3f9f-46a4-8698-819263b36f65"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,e4b733ed-3f9f-46a4-8698-819263b36f65.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / CryptoAPI</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=b255fe99-c7f7-496c-977a-272b95494fb4</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,b255fe99-c7f7-496c-977a-272b95494fb4.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,b255fe99-c7f7-496c-977a-272b95494fb4.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=b255fe99-c7f7-496c-977a-272b95494fb4</wfw:commentRss>
      <title>Создание самоподписанного сертификата средствами PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,b255fe99-c7f7-496c-977a-272b95494fb4.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,b255fe99-c7f7-496c-977a-272b95494fb4.aspx</link>
      <pubDate>Sun, 18 Apr 2010 09:46:11 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Самоподписанные сертификаты — это зло, за исключением сертификатов корневых CA. Я об этом говорил, говорю и буду говорить. Но в данном случае мы не преследуем цель создания самоподписанного сертификата. Нас по сути будет интересовать немного другое — рассмотрение принципа, который заложен во многих популярных тулзах как MakeCert или OpenSSL. Лично я не фанат ни первого, ни второго по своим сугубо личным причинам. Но, кроме этих двоих есть ещё утилита CertReq.exe, которая достаточно православная и вряд ли ей грозит вымирание (а жаль). Вобщем, сегодня предлагаю ещё раз поковырять CryptoAPI.&lt;/p&gt;  &lt;p&gt;Как мы уже знаем, &lt;a href="http://www.sysadmins.lv/CategoryView,category,PowerShellCryptoAPI.aspx"&gt;CryptoAPI&lt;/a&gt; обладает большим количеством всяческих COM интерфейсов, при помощи которых мы можем работать практически с любыми аспектами цифровых сертификатов. Некоторые из них бажные, а некоторые — не очень &lt;img alt=":)" src="/smilies/happy.gif"&gt;, но функционал у них впечатляющий. В настоящее время существует 2 основных набора API, которые реализуют клиентскую часть энроллмента — &lt;a href="http://msdn.microsoft.com/en-us/library/aa382482(VS.85).aspx" target="_blank"&gt;XEnroll&lt;/a&gt; и &lt;a href="http://msdn.microsoft.com/en-us/library/aa374850(VS.85).aspx" target="_blank"&gt;CertEnroll&lt;/a&gt;. Первый доступен только в системах начиная с Windows 2000 и до Windows Server 2003 включительно. В более новых версиях XEnroll был вырезан вместе с CAPICOM'ом полностью (куски CAPICOM'а ещё можно найти в висте) за ненадобностью. Семейство интерфейсов CertEnroll было значительно переработано и расширено, что делает его крайне гибким. Я не буду рассказывать про XEnroll, потому что это неинтересно и трупов пинать нехорошо.&lt;/p&gt;  &lt;p&gt;Многие считают, что CryptoAPI — это очень сложно. Я могу возразить им. Я не программист совсем, но могу достаточно свободно их использовать. Нашей отправной точкой будет MSDN по адресу: &lt;a href="http://msdn.microsoft.com/en-us/library/aa374874(VS.85).aspx"&gt;Certificate Enrollment API Reference&lt;/a&gt;. Эта секция содержит всё самое необходимое — описание интерфейсов и перечисления. И самый первый интерфейс, который мы видим — &lt;a href="http://msdn.microsoft.com/en-us/library/aa377809(VS.85).aspx" target="_blank"&gt;IX509Enrollment&lt;/a&gt;. Этот интерфейс реализует нечто промежуточное между клиентом и сервером. Мы можем по описанию найти то, что нам нужно, а именно первую секцию — Out-of-band-enrollment. И мы видим, что для него надо сначала вызвать метод &lt;a href="http://msdn.microsoft.com/en-us/library/aa377869(VS.85).aspx" target="_blank"&gt;CreateRequest()&lt;/a&gt;. Но прежде чем вызывать метод, нам надо создать форму сертификата, на основе которой будет создан запрос. Как я уже упоминал, мы будем делать самоподписанный сертификат, поэтому следующий интерфейс подойдёт нам как нельзя кстати — &lt;a href="http://msdn.microsoft.com/en-us/library/ee351612(VS.85).aspx" target="_blank"&gt;IX509CertificateRequestCertificate2&lt;/a&gt;. Вот давайте с него и начнём.&lt;/p&gt;  &lt;p&gt;Все указанные здесь и далее интерфейсы являются COM интерфейсами семейства X509Enrollment и эти объекты создаются следующим образом:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509CertificateRequestCertificate.1&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; как строятся такие команды? Поскольку это COM интерфейс, первую букву I в названии интерфейса меняем на букву C. Далее, если мы видим цифру 2 в конце названия интерфейса, в команде мы ставим точку и пишем число на единцу меньшее. Вот такие нехитрые правила.&lt;/p&gt;

&lt;p&gt;Прежде чем его начать использовать, нам надо инициализировать его. К сожалению документация на MSDN далеко не полная, поэтому будем искать нужные методы через PowerShell и командлет Get-Member:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cert | gm -MemberType methods


   TypeName: System.__ComObject#{728ab35a-217d-11da-b2a4-000e7bbb2b09}

Name                             MemberType Definition
----                             ---------- ----------
CheckPublicKeySignature          Method     void CheckPublicKeySignature (IX509PublicKey)
CheckSignature                   Method     void CheckSignature (Pkcs10AllowedSignatureTypes)
Encode                           Method     void Encode ()
GetCspStatuses                   Method     ICspStatuses GetCspStatuses (X509KeySpec)
GetInnerRequest                  Method     IX509CertificateRequest GetInnerRequest (InnerRequestLevel)
Initialize                       Method     void Initialize (X509CertificateEnrollmentContext)
InitializeDecode                 Method     void InitializeDecode (string, EncodingType)
InitializeFromCertificate        Method     void InitializeFromCertificate (X509CertificateEnrollmentContext, string...
InitializeFromPrivateKey         Method     void InitializeFromPrivateKey (X509CertificateEnrollmentContext, IX509Pr...
InitializeFromPrivateKeyTemplate Method     void InitializeFromPrivateKeyTemplate (X509CertificateEnrollmentContext,...
InitializeFromPublicKey          Method     void InitializeFromPublicKey (X509CertificateEnrollmentContext, IX509Pub...
InitializeFromTemplate           Method     void InitializeFromTemplate (X509CertificateEnrollmentContext, IX509Enro...
InitializeFromTemplateName       Method     void InitializeFromTemplateName (X509CertificateEnrollmentContext, string)
IsSmartCard                      Method     bool IsSmartCard ()
ResetForEncode                   Method     void ResetForEncode ()


&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans]&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Из всех методов нам по сути доступен только &lt;strong&gt;InitializeFromPrivateKey()&lt;/strong&gt;, поскольку остальные методы инициализации требуют наличие доступа к Certification Authority. Посмотрим что требуется для этого метода:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cert | gm -MemberType methods | ?{$_.name -eq &amp;quot;InitializeFromPrivateKey&amp;quot;} | select definition

Definition
----------
void InitializeFromPrivateKey (X509CertificateEnrollmentContext, IX509PrivateKey, string)


&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans]&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;В качестве аргументов метода нам надо указать контекст энроллмента и объект закрытого ключа. Значения контекста находятся здесь: &lt;a href="http://msdn.microsoft.com/en-us/library/aa379399(VS.85).aspx"&gt;X509CertificateEnrollmentContext&lt;/a&gt; (просто включаете поиск на MSDN по названию перечисления). В качестве контекста мы можем выбрать контекст текущего пользователя или компьютера (остальное нас сейчас не волнует совсем). Контекст пользователя имеет значение 0x1. Так и запишем. Но этого мало. Надо ещё создать &lt;a href="http://msdn.microsoft.com/en-us/library/aa378921(VS.85).aspx" target="_blank"&gt;объект закрытого ключа&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509PrivateKey&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Этот интерфейс позволяет задавать различные параметры закрытого ключа, но мы обойдёмся лишь самым необходимым:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; во-первых надо указать CSP. Выберем самый простой криптопровайдер&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.ProviderName &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Microsoft Base Cryptographic Provider v1.0&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; закрытый ключ будет использоваться для подписи (Digital Signature)&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa379409(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.KeySpec &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;0x2&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; длина вполне стандартная&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.Length &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;1024&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; ключ будем хранить в пользовательском хранилище&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.MachineContext &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;0x0&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; и генерируем ключ&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.Create()&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Ура! Мы сгенерировали ключ. Теперь вернёмся к предыдущему интерфейсу и инициализируем его из закрытого ключа:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeFromPrivateKey(&lt;/span&gt;&lt;span style="color: #000000"&gt;0x1&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Мы указываем контекст текущего пользователя и объект закрытого ключа. Там есть ещё один аргумент, который называется String. Я не знаю, что они этим хотели сказать, поэтому оставляем пустую строку. А теперь вернёмся к интерфейсу &lt;a href="http://msdn.microsoft.com/en-us/library/ee351612(VS.85).aspx" target="_blank"&gt;IX509CertificateRequestCertificate2&lt;/a&gt; и посмотрим, что мы можем сделать сейчас. Например, используя свойства NotBefore и NotAfter мы зададим срок действия сертификата. Например, 1 год с сегодняшнего дня:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotBefore &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; [&lt;/span&gt;&lt;span style="color: #008080"&gt;datetime&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;Now&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotAfter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotBefore.AddDays(&lt;/span&gt;&lt;span style="color: #000000"&gt;365&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Теперь нам надо добавить следующие свойства: EncancedKeyUsage (т.е. для каких целей вообще будет использоваться сертификат), Subject (на кого будет выписан сертификат) и Issuer (кто выдал этот сертификат). Поскольку у нас самоподписанный сертификат, поле Subject и Issuer будут одинаковые. На MSDN'е не хватает документации по свойствам Issuer и Subject, но у нас есть поиск, который нас приведёт сюда: &lt;a href="http://msdn.microsoft.com/en-us/library/aa377051(VS.85).aspx" target="_blank"&gt;IX500DistinguishedName&lt;/a&gt;. Поля Subject и Issuer должны заполняться в формате Distinguished Name и доступные префиксы для DN достаточно понятно расписаны в таблице. Нам нужно как-то активировать этот объект. Методов для инициализации здесь нет, поэтому будем использовать метод Encode().&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Лирическое отступление:&lt;/font&gt;&lt;/strong&gt; в подавляющем большинстве случаев вы не можете присваивать значения свойствам объектов после создания самих объектов. Предварительно их надо «активировать» одним из двух способов. Если у объекта есть метод Initialize или производное от него, необходимо сначала воспользоваться одним из доступных методов инициализации. Если объект не содержит явных методов инициализации, нужно воспользоваться методом Encode, который кодирует объект или строку в ASN.1 DER строку и инициализирует объект. Единственным исключением из этого правила являются коллекции объектов. Они как правило используют метод &lt;strong&gt;Add()&lt;/strong&gt; для добавления уже инициализированных объектов.&lt;/p&gt;

&lt;p&gt;Уже с главной страницы &lt;a href="http://msdn.microsoft.com/en-us/library/aa377051(VS.85).aspx" target="_blank"&gt;IX500DistinguishedName&lt;/a&gt; видно, что &lt;a href="http://msdn.microsoft.com/en-us/library/aa377054(VS.85).aspx" target="_blank"&gt;Encode&lt;/a&gt; кодирует строку, которая записана в DN формате. Поэтому вызываем этот метод:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$SubjectDN&lt;/span&gt;&lt;span style="color: #000000"&gt;.Encode(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;CN=Some Subject,DC=lucernepublishing,DC=COM&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;0x0&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;После строки нужно ещё указать флаг, в котором указана строка DN. Ставим дефолтный флаг. Теперь у нас готово поле Subject и Issuer (как мы договаривались, они будут одинаковые). Давайте их прицепим к нашему шаблону сертификата:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$SubjectDN&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Issuer &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Что нам осталось сделать? Нам надо создать расширение Enchanced Key Usage. Для этого нам надо использовать следующий интерфейс: &lt;a href="http://msdn.microsoft.com/en-us/library/aa378132(VS.85).aspx" target="_blank"&gt;IX509ExtensionEnhancedKeyUsage&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$EKU&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509ExtensionEnhancedKeyUsage&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Данный объект инициализируется из коллекции объектов &lt;a href="http://msdn.microsoft.com/en-us/library/aa376785(VS.85).aspx" target="_blank"&gt;IObjectIds&lt;/a&gt;. Давайте создадим эту коллекцию:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$OIDs&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CObjectIDs&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;В эту коллекцию с использованием метода Add() надо добавить один или несколько объектов &lt;a href="http://msdn.microsoft.com/en-us/library/aa376784(VS.85).aspx" target="_blank"&gt;IObjectId&lt;/a&gt;, каждый из которых представляет конкретное предназначение сертификата. Например, Server Authentication, Client Authentication, Smart Card Logon, Secure e-mail и т.д. Но мы сделаем сертификат для Code Signing. OID этого EKU = 1.3.6.1.5.5.7.3.3. Вот и сделаем его:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; создаём объект IObjectID&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$OID&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CObjectID&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; инициализируем его с использованием Code Signing&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$OID&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeFromValue(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;1.3.6.1.5.5.7.3.3&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; добавляем наш OID в коллекцию OID'ов&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$OIDs&lt;/span&gt;&lt;span style="color: #000000"&gt;.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$OID&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; добавляем коллекцию в объект IX509ExtensionEnhancedKeyUsage&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$EKU&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeEncode(&lt;/span&gt;&lt;span style="color: #800080"&gt;$OIDs&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;объект EKU у нас готов, теперь его надо добавить в наш шаблон сертификата. Поскольку это не стандартное поле сертификата, а расширение, добавляем этот объект в свойство X509Extensions, которое является аналогом интерфейса IX509Extensions и, который в свою очередь, является коллекцией расширений. Поэтому добавляем наше расширение методом &lt;a href="http://msdn.microsoft.com/en-us/library/aa378242(VS.85).aspx" target="_blank"&gt;Add()&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.X509Extensions.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$EKU&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Всё, мы собрали все минимально необходимые поля и расширения:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cert


Type                        : 4
EnrollmentContext           : 1
Silent                      : False
ParentWindow                :
UIContextMessage            :
SuppressDefaults            : False
ClientId                    :
CspInformations             : System.__ComObject
HashAlgorithm               : System.__ComObject
AlternateSignatureAlgorithm : False
TemplateObjectId            :
PublicKey                   : System.__ComObject
PrivateKey                  : System.__ComObject
NullSigned                  : False
ReuseKey                    : False
Subject                     : System.__ComObject
CspStatuses                 : System.__ComObject
SmimeCapabilities           : False
SignatureInformation        : System.__ComObject
KeyContainerNamePrefix      : lp
CryptAttributes             :
X509Extensions              : System.__ComObject
CriticalExtensions          : System.__ComObject
SuppressOids                : System.__ComObject
Issuer                      : System.__ComObject
NotBefore                   : 16.04.2010 18:25:22
NotAfter                    : 16.04.2011 18:25:22
SignerCertificate           :
PolicyServer                :
Template                    :



&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans]&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Теперь мы можем превращать наш шаблон сертификата в настоящй сертификат.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Лирическое отступление:&lt;/font&gt;&lt;/strong&gt; а что такое запрос в техническом смысле? На самом деле запрос ничем не отличается от сертификата. Когда вы запрашиваете сертификат у CA, клиент использует эти же интерфейсы для генерации запроса. При этом получается самый настоящий самоподписанный сертификат, где Subject и Issuer одинаковые и равны имени текущего пользователя или компьютера, а так же содержит все необходимые расширения. Сам запрос подписывается закрытым ключом, который мы сгенерировали. По большому счёту, его уже можно использовать как настоящий самоподписанный сертификат. Если его отправить на сервер CA, то последний просто подменяет значения необходимых полей (как Issuer, в котором он ставит себя) и расширений, удаляет старую подпись и подписывает сертификат новой подписью. Вы можете убедиться в этом очень просто. Сгенерируйте запрос для сертификата, откройте оснастку Certificates и разверните секцию &lt;strong&gt;Certificate Enrollment Requests&lt;/strong&gt;. Там будет этот самый запрос в виде уже готового сертификата. Просто там он ждёт, пока какой-нибудь CA не подпишет его.&lt;/p&gt;

&lt;p&gt;Давайте вернёмся в самое начало текущего поста и вспомним про «исходный предмет» — &lt;a href="http://msdn.microsoft.com/en-us/library/aa377809(VS.85).aspx" target="_blank"&gt;IX509Enrollment&lt;/a&gt;. Вот этот интерфейс нам сконвертирует шаблон сертификата в настоящий сертификат с использованием метода &lt;a href="http://msdn.microsoft.com/en-us/library/aa377869(VS.85).aspx" target="_blank"&gt;CreateRequest()&lt;/a&gt;. Но прежде чем использовать метод, нам надо инициализировать объект:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509enrollment&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeFromRequest(&lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;И генерируем файл запроса, который ничем не отличается от самоподписанного сертификата:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$endCert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt;.CreateRequest(&lt;/span&gt;&lt;span style="color: #000000"&gt;0x0&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;В аргументах метода указываем кодировку согласно этой страничке: &lt;a href="http://msdn.microsoft.com/en-us/library/aa374936(VS.85).aspx" target="_blank"&gt;EncodingType Enumeration&lt;/a&gt;. Мы выбираем Base64 с заголовками. $endCert будет содержать сам сертификат (открытую его часть). Фактически запрос хранится в контейнере &lt;strong&gt;Certificate Enrollment Requests&lt;/strong&gt;. Поскольку этот интерфейс не был задуман специально для самоподписанных сертификатов мы проходим стандартную процедуру установки сертификата. Мы просто берём открытую часть нашего же сертификата и устанавливаем её. Вот, кстати, как он выглядит:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $endcert
-----BEGIN CERTIFICATE-----
MIICaTCCAdKgAwIBAgIQEzCS/mFIxLBAiGjz7+n0dDANBgkqhkiG9w0BAQUFADBP
MRMwEQYKCZImiZPyLGQBGRYDQ09NMSEwHwYKCZImiZPyLGQBGRYRbHVjZXJuZXB1
Ymxpc2hpbmcxFTATBgNVBAMMDFNvbWUgU3ViamVjdDAeFw0xMDA0MTgxMTI5MDla
Fw0xMTA0MTgxMTI5MDlaME8xEzARBgoJkiaJk/IsZAEZFgNDT00xITAfBgoJkiaJ
k/IsZAEZFhFsdWNlcm5lcHVibGlzaGluZzEVMBMGA1UEAwwMU29tZSBTdWJqZWN0
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDBGa+PnrhnOFO5+76c5zX5/+xh
Kb2hUYl/pRuIKzYcqrmkvqjpPK/McusibT1h70emUkED0TSZsAlSivdIFK6WSxn6
HsTCaGIHhyOSKAvzQkBsZ74BPEydGT5LiX0+MOTyxwFAHhb+bqfbkdkXqUSkJAHK
Z6p+fgX8uaJkKjL/kwIDAQABo0YwRDATBgNVHSUEDDAKBggrBgEFBQcDAzAdBgNV
HQ4EFgQUzIFwoRTY6KjUiqmjWjSjlkxbNncwDgYDVR0PAQH/BAQDAgeAMA0GCSqG
SIb3DQEBBQUAA4GBACizodCpl/cF3OGLUx8HVag0yhr1e1P8+CLPc31FmCPAY1CO
T0yxyJPoafkbXKRjclevNJdvxE3ys9fyYigFUhgswh3oWmjanDaatPKa0kE4147k
SQHvN8JP20KeDDCJBk/FbS3xCn3jTix90ddzTa1uFoqBbBNbKOaDHIrqypTY
-----END CERTIFICATE-----

&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans]&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Система приклеит этот сертификат к шаблону сертификата и переложит его уже в контейнер Personal:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt;.InstallResponse(&lt;/span&gt;&lt;span style="color: #000000"&gt;0x2&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800080"&gt;$endCert&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0x0&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Всё, теперь мы увидим этот сертификат в нашем хранилище и который готов к использованию. Я немного переработал код и обернул его в красивую функцию, которая будет делать следующее:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Генерировать тестовый самоподписанный сертификат для подписи скриптов PowerShell &lt;/li&gt;

  &lt;li&gt;Устанавливать сертификат с закрытым ключом в контейнер Personal &lt;/li&gt;

  &lt;li&gt;Устанавливать открытую часть сертификата в Trusted Root CAs для обеспечения доверия этому сертификату &lt;/li&gt;

  &lt;li&gt;Устанавливать открытую часть сертификата в Trusted Publishers для задания явного доверия цифровым подписям, сделанные этим сертификатом. &lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt;####################################################################&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Create PowerShell cert.ps1&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Version 1.0&lt;/span&gt;&lt;span style="color: #008000"&gt;
#
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Creates self-signed signing certificate and install it to certificate store&lt;/span&gt;&lt;span style="color: #008000"&gt;
#
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Note: Requires at least Windows Vista. Windows XP/Windows Server 2003&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; are not supported.&lt;/span&gt;&lt;span style="color: #008000"&gt;
#
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Vadims Podans (c) 2010&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://www.sysadmins.lv/&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt;####################################################################&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt;requires -Version 2.0&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;New-SigningCert&lt;/span&gt;&lt;span style="color: #000000"&gt; {
&lt;/span&gt;&lt;span style="color: #008000"&gt;&amp;lt;#&lt;/span&gt;&lt;span style="color: #008000"&gt;
.Synopsis
    Creates self-signed signing certificate and install it to certificate store
.Description
    This function generates self-signed certificate with some pre-defined and
    user-definable settings. User may elect to perform complete certificate
    installation, by installing generated certificate to Trusted Root Certification
    Authorities and Trusted Publishers containers in *current user* store.
    
.Parameter Subject
    Specifies subject for certificate. This parameter must be entered in X500
    Distinguished Name format. Default is: CN=PowerShell User, OU=Test Signing Cert.

.Parameter KeyLength
    Specifies private key length. Due of performance and security reasons, only
    1024 and 2048 bit are supported. by default 1024 bit key length is used.

.Parameter NotBefore
    Sets the date in local time on which a certificate becomes valid. By default
    current date and time is used.

.Parameter NotAfter
    Sets the date in local time after which a certificate is no longer valid. By
    default certificate is valid for 365 days.

.Parameter Force
    If Force switch is asserted, script will prepare certificate for use by adding
    it to Trusted Root Certification Authorities and Trusted Publishers containers
    in current user certificate store. During certificate installation you will be
    prompted to confirm if you want to add self-signed certificate to Trusted Root
    Certification Authorities container.
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;
[CmdletBinding()]
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;param&lt;/span&gt;&lt;span style="color: #000000"&gt; (
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;string&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$Subject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;CN=PowerShell User, OU=Test Signing Cert&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;,
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;int&lt;/span&gt;&lt;span style="color: #000000"&gt;][ValidateSet(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;1024&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;2048&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)]&lt;/span&gt;&lt;span style="color: #800080"&gt;$KeyLength&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;1024&lt;/span&gt;&lt;span style="color: #000000"&gt;,
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;datetime&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$NotBefore&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; [&lt;/span&gt;&lt;span style="color: #008080"&gt;DateTime&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;Now&lt;/span&gt;&lt;span style="color: #000000"&gt;,
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;datetime&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$NotAfter&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$NotBefore&lt;/span&gt;&lt;span style="color: #000000"&gt;.AddDays(&lt;/span&gt;&lt;span style="color: #000000"&gt;365&lt;/span&gt;&lt;span style="color: #000000"&gt;),
        [&lt;/span&gt;&lt;span style="color: #008080"&gt;switch&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$Force&lt;/span&gt;&lt;span style="color: #000000"&gt;
    )
    
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$OS&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Get-WmiObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Win32_OperatingSystem&lt;/span&gt;&lt;span style="color: #000000"&gt;).Version
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$OS&lt;/span&gt;&lt;span style="color: #000000"&gt;[0] &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-lt&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;6&lt;/span&gt;&lt;span style="color: #000000"&gt;) {
        &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Write-Warning&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Windows XP, Windows Server 2003 and Windows Server 2003 R2 are not supported!&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;
        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;return&lt;/span&gt;&lt;span style="color: #000000"&gt;
    }
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; while all certificate fields MUST be encoded in ASN.1 DER format&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; we will use CryptoAPI COM interfaces to generate and encode all necessary&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; extensions.&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; create Subject field in X.500 format using the following interface:&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa377051(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$SubjectDN&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX500DistinguishedName&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$SubjectDN&lt;/span&gt;&lt;span style="color: #000000"&gt;.Encode(&lt;/span&gt;&lt;span style="color: #800080"&gt;$Subject&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;0x0&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; define CodeSigning enhanced key usage (actual OID = 1.3.6.1.5.5.7.3.3) from OID&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa376784(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$OID&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CObjectID&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$OID&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeFromValue(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;1.3.6.1.5.5.7.3.3&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; while IX509ExtensionEnhancedKeyUsage accept only IObjectID collection&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; (to support multiple EKUs) we need to create IObjectIDs object and add our&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; IObjectID object to the collection:&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa376785(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$OIDs&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CObjectIDs&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$OIDs&lt;/span&gt;&lt;span style="color: #000000"&gt;.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$OID&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; now we create Enhanced Key Usage extension, add our OID and encode extension value&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa378132(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$EKU&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509ExtensionEnhancedKeyUsage&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$EKU&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeEncode(&lt;/span&gt;&lt;span style="color: #800080"&gt;$OIDs&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; generate Private key as follows:&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa378921(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.ProviderName &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Microsoft Base Cryptographic Provider v1.0&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; private key is supposed for signature: http://msdn.microsoft.com/en-us/library/aa379409(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.KeySpec &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;0x2&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.Length &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$KeyLength&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; key will be stored in current user certificate store&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.MachineContext &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;0x0&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;.Create()
    
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; now we need to create certificate request template using the following interface:&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; http://msdn.microsoft.com/en-us/library/aa377124(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509CertificateRequestCertificate&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeFromPrivateKey(&lt;/span&gt;&lt;span style="color: #000000"&gt;0x1&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800080"&gt;$PrivateKey&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$SubjectDN&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Issuer &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotBefore &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$NotBefore&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotAfter &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$NotAfter&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.X509Extensions.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$EKU&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; completing certificate request template building&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Encode()
    
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; now we need to process request and build end certificate using the following&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; interface: http://msdn.microsoft.com/en-us/library/aa377809(VS.85).aspx&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ComObject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;X509Enrollment.CX509enrollment&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; process request&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt;.InitializeFromRequest(&lt;/span&gt;&lt;span style="color: #800080"&gt;$Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; retrievecertificate encoded in Base64.&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$endCert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt;.CreateRequest(&lt;/span&gt;&lt;span style="color: #000000"&gt;0x1&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; install certificate to user store&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$Request&lt;/span&gt;&lt;span style="color: #000000"&gt;.InstallResponse(&lt;/span&gt;&lt;span style="color: #000000"&gt;0x2&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800080"&gt;$endCert&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0x1&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)
    
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$Force&lt;/span&gt;&lt;span style="color: #000000"&gt;) {
        &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; convert Bas64 string to a byte array&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;         [&lt;/span&gt;&lt;span style="color: #008080"&gt;Byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[]]&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; [&lt;/span&gt;&lt;span style="color: #008080"&gt;System.Convert&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;FromBase64String&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800080"&gt;$endCert&lt;/span&gt;&lt;span style="color: #000000"&gt;)
        &lt;/span&gt;&lt;span style="color: #0000ff"&gt;foreach&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$Container&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #0000ff"&gt;in&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Root&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;TrustedPublisher&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;) {
            &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; open Trusted Root CAs and TrustedPublishers containers and add&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;            &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; certificate&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;            &lt;/span&gt;&lt;span style="color: #800080"&gt;$x509store&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Security.Cryptography.X509Certificates.X509Store&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$Container&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;CurrentUser&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;
            &lt;/span&gt;&lt;span style="color: #800080"&gt;$x509store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Open([&lt;/span&gt;&lt;span style="color: #008080"&gt;Security.Cryptography.X509Certificates.OpenFlags&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;ReadWrite&lt;/span&gt;&lt;span style="color: #000000"&gt;)
            &lt;/span&gt;&lt;span style="color: #800080"&gt;$x509store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Add([&lt;/span&gt;&lt;span style="color: #008080"&gt;Security.Cryptography.X509Certificates.X509Certificate2&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes&lt;/span&gt;&lt;span style="color: #000000"&gt;)
            &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; close store when operation is completed&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;            &lt;/span&gt;&lt;span style="color: #800080"&gt;$x509store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Close()
        }
    }
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;С виду кажется сложно, но на самом деле тут ничего сложного нет совсем. Просто представьте себе сертификат как большую матрёшку, в которую вы вкладываете другие маленькие матрёшки, которые представляют собой поля и расширения сертификатов. Начинаете собирать самые маленькие матрёшки, вкладываете в более большие и в конечном итоге собираете настоящий сертификат. Хоть документация на MSDN не очень полная, используя командлет &lt;strong&gt;Get-Member&lt;/strong&gt; вы можете восполнить этот пробел.&lt;/p&gt;

&lt;div&gt;
  &lt;p style="border-bottom: silver 1px solid; position: relative; border-left: silver 1px solid; width: 240px; height: 66px; border-top: silver 1px solid; border-right: silver 1px solid"&gt;&lt;span style="font-family: verdana,arial,sans-serif; cursor: pointer"&gt;&lt;a style="border-right-width: 0px; width: 240px; border-top-width: 0px; border-bottom-width: 0px; height: 66px; border-left-width: 0px" href="http://www.sysadmins.lv/content/scripts/new-signingcert.ps1" target="_self"&gt;&lt;img style="border-right-width: 0px; width: 240px; border-top-width: 0px; border-bottom-width: 0px; height: 66px; border-left-width: 0px" alt="Download File" src="http://www.sysadmins.lv/images/buttons/transparent.gif" /&gt; &lt;/a&gt;&lt;a style="border-right-width: 0px; border-top-width: 0px; border-bottom-width: 0px; border-left-width: 0px" href="http://www.sysadmins.lv/content/scripts/new-signingcert.ps1" target="_self"&gt;&lt;img style="position: absolute; top: 6px; left: 5px" alt="Download File" src="http://www.sysadmins.lv/images/buttons/pgui.png" width="48" height="45" /&gt; &lt;/a&gt;&lt;a style="text-decoration: none" href="http://www.sysadmins.lv/content/scripts/new-signingcert.ps1" target="_self"&gt;&lt;span style="position: absolute; width: 167px; white-space: nowrap; color: #555555; overflow: hidden; top: 7px; margin-right: 5px; left: 67px"&gt;&lt;span style="display: block; visibility: hidden"&gt;1&lt;/span&gt; &lt;span style="line-height: 1.25em; display: block; cursor: pointer; text-decoration: none; padding-top: 1px" title="Download file"&gt;PS1 file 
            &lt;br /&gt;13,1 KB &lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;a style="position: absolute; width: 167px; white-space: nowrap; color: #0066a7; overflow: hidden; top: 7px; margin-right: 5px; text-decoration: none; left: 67px" href="http://www.sysadmins.lv/content/scripts/new-signingcert.ps1" target="_self" alt="Download File"&gt;New-SigningCert.ps1&lt;/a&gt; &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=b255fe99-c7f7-496c-977a-272b95494fb4"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,b255fe99-c7f7-496c-977a-272b95494fb4.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
      <category>PowerShell / CryptoAPI</category>
      <category>PowerShell / Digital Signatures</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=eabb97f4-c14f-41ef-bc4c-c3df83ecd98f</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,eabb97f4-c14f-41ef-bc4c-c3df83ecd98f.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,eabb97f4-c14f-41ef-bc4c-c3df83ecd98f.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=eabb97f4-c14f-41ef-bc4c-c3df83ecd98f</wfw:commentRss>
      <title>CryptoAPI и управление Certification Authority с помощью PowerShell (часть 4)</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,eabb97f4-c14f-41ef-bc4c-c3df83ecd98f.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,eabb97f4-c14f-41ef-bc4c-c3df83ecd98f.aspx</link>
      <pubDate>Fri, 20 Nov 2009 16:40:36 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;В продолжении темы исследования COM интерфейсов CryptoAPI для управления службами Certificate Services предлагаю теперь разобрать вопросы KRA — Key Recovery Agents. Сначала напомню уже изученные темы по CryptoAPI:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx"&gt;&lt;strong&gt;CryptoAPI и управление Certification Authority с помощью PowerShell&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,ca3a2177-92b3-46af-bc7b-0497cdbce74e.aspx"&gt;&lt;strong&gt;CryptoAPI и управление Certification Authority с помощью PowerShell (часть 2)&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx"&gt;&lt;strong&gt;CryptoAPI и управление Certification Authority с помощью PowerShell (часть 3)&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;И на сегодня наш план выглядит достаточно интересно:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Получение списка доступных KRA в лесу и просмотр их сертификатов &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Получение списка KRA назначенных на сервере CA; &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Назначение новых KRA для CA.&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;h1 align="center"&gt;Получение списка доступных KRA в лесу&lt;/h1&gt;  &lt;p&gt;KRA используется для архивирования закрытых ключей сертификатов в БД CA. В случае если пользователь уничтожил свой закрытый ключ он может его восстановить. Для этого нужно обратиться к администратору CA для извлечения &lt;strong&gt;BLOB&lt;/strong&gt; (&lt;em&gt;Binary Large OBject&lt;/em&gt;) в файл. После чего агент восстановления (&lt;strong&gt;KRA&lt;/strong&gt;) использует свой закрытый ключ для расшифровки закрытого ключа из BLOB'а. Учитывая, что я и не только уже рассматривали этот вопрос, я не буду пересказывать принцип работы Key Archival:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,a13d0c06-3608-42d9-b11e-0aef08354dd8.aspx"&gt;&lt;strong&gt;EFS и смарт-карты в Windows Server 2008 (часть 2)&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,8b5e58cc-9017-4575-9c9c-17dd81c25866.aspx"&gt;&lt;strong&gt;EFS и смарт-карты в Windows Server 2008 (часть 3)&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://blogs.technet.com/pki/archive/2009/08/07/understanding-key-archival.aspx"&gt;&lt;strong&gt;Understanding Key Archival&lt;/strong&gt;&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Все сертификаты KRA публикуются в forest naming configuration context партиции AD и реплицируется между всеми контроллерами в лесу. Публикация просисходит в точке:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;CN=KRA, CN=Public Key Services, CN=Services, CN=Configuration, DC=ForestRootDomain&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;div style="width: 935px"&gt;   &lt;blockquote&gt;     &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $ldap = [ADSI]&amp;quot;LDAP://CN=KRA, CN=Public Key Services, CN=Services, CN=Configuration, DC=contoso,dc=com&amp;quot;
PS C:\&amp;gt; $ldap

distinguishedName
-----------------
{CN=KRA,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com}


PS C:\&amp;gt; $kra = $ldap.psbase.children | %{$_}
PS C:\&amp;gt; $kra

distinguishedName
-----------------
{CN=contoso-DC2-CA,CN=KRA,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com}
{CN=Contoso CA,CN=KRA,CN=Public Key Services,CN=Services,CN=Configuration,DC=contoso,DC=com}&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Мы получили список CA в лесу и посмотрев каждый из них можем посмотреть сколько KRA сертификатов выпустил каждый CA:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $kra[1] | fl *


objectClass            : {top, msPKI-PrivateKeyRecoveryAgent}
cn                     : {Contoso CA}
userCertificate        : {48 130 6 104 48 130 5 80 160 3 2 1 2 2 10 21 29 22 96 0 0 0 0 0 4 48 13 6 9 42 134 72 134 247
                          13 1 1 5 5 0 48 67 49 19 48 17 6 10 9 146 38 137 147 242 44 100 1 25 22 3 99 111 109 49 23 48
                          21 6 10 9 146 38 137 147 242 44 100 1 25 22 7 99 111 110 116 111 115 111 49 19 48 17 6 3 85 4
                          3 19 10 67 111 110 116 111 115 111 32 67 65 48 30 23 13 48 57 48 50 49 53 49 53 48 53 50 53 9
                         0 23 13 49 49 48 50 49 53 49 53 48 53 50 53 90 48 86 49 19 48 17 6 10 9 146 38 137 147 242 44
                         100 1 25 22 3 99 111 109 49 23 48 21 6 10 9 146 38 137 147 242 44 100 1 25 22 7 99 111 110 116
&amp;lt;...&amp;gt;
&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Свойство &lt;strong&gt;UserCertificate&lt;/strong&gt; в виде массива может содержать сертификаты KRA в виде байтового массива. Например, указанный CA выпустил 2 сертификата KRA:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $kra[1].usercertificate.count
2&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;И обратившись к индексам этого свойства можно получить конкретные сертификаты: $kra[1].usercertificate[0]. Если CA не выпускал сертификаты для KRA, то свойство UserCertificate будет содержать число ноль:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $kra[0] | fl *


objectClass            : {top, msPKI-PrivateKeyRecoveryAgent}
cn                     : {contoso-DC2-CA}
userCertificate        : {0}
&amp;lt;...&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Поэтому для получения всех сертификатов KRA нужно пройтись по всем членам CN=KRA и выбрать из них ненулевые значения свойства UserCertificate. Если сертификатов больше, чем 1, то они будут храниться в этом свойстве в виде массива. Чтобы посмотреть сам сертификат, вы можете просто сохранить этот массив байтов в файл:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; [System.IO.File]::WriteAllBytes(&amp;quot;C:\kra.cer&amp;quot;,$kra[1].usercertificate[1])
PS C:\&amp;gt; &amp;amp; .\kra.cer&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;h1 align="center"&gt;Получение списка KRA назначенных на сервере CA&lt;/h1&gt;

&lt;p&gt;А теперь вернёмся к интерфейсу ICertAdmin2. С его помощью мы можем посмотреть количество агентов восстановления, которые назначены на CA и посмотреть их сертификаты. Однако, этот интерфейс имеет какой-то баг с PropID, которые связаны с KRA, о которых я писал в &lt;a href="http://www.sysadmins.lv/PermaLink,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx"&gt;&lt;strong&gt;предыдущей статье&lt;/strong&gt;&lt;/a&gt;, поэтому для получения этих данных мы будем использовать интерфейс &lt;a href="http://msdn.microsoft.com/en-us/library/ee373776(VS.85).aspx"&gt;&lt;strong&gt;ICertRequest3&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $CertRequest = New-Object -ComObject CertificateAuthority.Request.1
PS C:\&amp;gt; $CertRequest.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;,0x18,0,1,0)
1
PS C:\&amp;gt; $CertRequest.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x18,0,1,0)
0
PS C:\&amp;gt; $CertRequest.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;,0x19,0,1,0)
1
PS C:\&amp;gt; $CertRequest.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x19,0,1,0)
0&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Мы видим, что на сервере DC1 назначен 1 агент восстановления, а на DC2 ни одного. Сегодня мы добавим агентов восстановления на DC2.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; чем отличаются &lt;strong&gt;KRACERTUSEDCOUNT&lt;/strong&gt; и &lt;strong&gt;KRACERTCOUNT&lt;/strong&gt;? KRACERTCOUNT показывает сколько всего KRA назначено на конкретном сервере CA. А KRACERTUSEDCOUNT показывает сколько из них будет использовать CA при архивации каждого закрытого ключа сертификата и это число может быть меньше, чем общее количество сертификатов KRA. В таком случае CA рандомно выбирает KRACERTUSEDCOUNT сертификатов и шифрует ими закрытый ключ. Например, KRACERTCOUNT = 5, а KRACERTUSEDCOUNT = 3, то CA при архивации ключа выберет рандомно 3 сертификата KRA из списка и зашифрует ими ключ. И только эти 3 агента восстановления могут восстановить ключ, а остальные 2 уже не смогут.&lt;/p&gt;

&lt;h1 align="center"&gt;&lt;strong&gt;Получение списка KRA назначенных на сервере CA&lt;/strong&gt;&lt;/h1&gt;

&lt;p&gt;Чтобы посмотреть сами сертификаты KRA, мы должны воспользоваться &lt;strong&gt;PropID = CR_PROP_KRACERT (0x1A)&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;И вот что мы увидим:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $CertAdmin.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;,0x1A,0,3,0)
-----BEGIN CERTIFICATE-----
MIIGaDCCBVCgAwIBAgIKFR0WYAAAAAAABDANBgkqhkiG9w0BAQUFADBDMRMwEQYK
CZImiZPyLGQBGRYDY29tMRcwFQYKCZImiZPyLGQBGRYHY29udG9zbzETMBEGA1UE
AxMKQ29udG9zbyBDQTAeFw0wOTAyMTUxNTA1MjVaFw0xMTAyMTUxNTA1MjVaMFYx
EzARBgoJkiaJk/IsZAEZFgNjb20xFzAVBgoJkiaJk/IsZAEZFgdjb250b3NvMQ4w
DAYDVQQDEwVVc2VyczEWMBQGA1UEAxMNQWRtaW5pc3RyYXRvcjCCASIwDQYJKoZI
hvcNAQEBBQADggEPADCCAQoCggEBAJG7T5yMninhrkXFQU8WGUr5BYYUeOz10Rkn
&amp;lt;...&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;В нулевом индексе мы видим первый сертификат. Последующие будут храниться в других индексах:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#0000ff"&gt;$CertAdmin.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;,0x1A,$Index,3,0)&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Этот сертификат можно спокойно записать в файл и через GUI просмотреть его свойства. Но вообще это не родной формат сертификата KRA для данного интерфейса, поскольку добавлять сертификаты KRA на сервере CA нужно в &lt;strong&gt;ASN1 DER-encoded string&lt;/strong&gt; формате. Т.е. &lt;strong&gt;Flags&lt;/strong&gt; должен быть не 0, а 2:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#0000ff"&gt;$CertAdmin.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;,0x1A,$Index,3,&lt;strong&gt;2&lt;/strong&gt;)&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;и увидим примерно такое:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $kra = $CertAdmin.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;,0x1a,0,3,2)
PS C:\&amp;gt; $kra
?????A???`  ?????c?♣??????????????????T???????????????????????????????????????T????????????????????????????????????????
??ca♣??????☺???????????????????????????????????????????????????????????????????????????????????????????????????????????
??????????????????????☺????????Є?????????????????☻???????☻??????????????ЎЖ?????????????CA??????Ё????????????h??A???????
??????????????????????????????????????????????╣????????????????????????????????????????????????????????????????????????
?????????????????????C?cЁ??????C???????????????????????????????????????????????????????????????????????????????????????
???????????????????????????????????????Х???CA?????Ё???????CA?????Б????CA??????????????????????a???☺????????????????????
????????????????????????????????????c?????????????????????????????????????H╝??????????????????{?????????????&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;выглядит весьма уныло, но вот в таком формате и надо записывать сертификаты агентов восстановления в CA.&lt;/p&gt;

&lt;h1 align="center"&gt;Назначение новых KRA для CA&lt;/h1&gt;

&lt;p&gt;Когда мы рассмотрели основные моменты связанные с агентами восстановления в контексте CryptoAPI, мы можем приступить к финальной части — назначению новых агентов восстановления. В принципе, здесь нет ничего сложного, поскольку для добавления KRA нужно сделать 5 вещи:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Получить массив байтов, которые бы представляли сертификат агента восстановления откуда угодно. Хоть из AD, хоть из файла сертификата; &lt;/li&gt;

  &lt;li&gt;Используя специальный конвертер, разобрать этот массив на пары байтов, сконвертировать эти пары в little-endian hex строку, получить десятичное представление этой hex-строки и получить итоговую символьную строку; &lt;/li&gt;

  &lt;li&gt;Записать эту строку используя метод SetCAProperty(); &lt;/li&gt;

  &lt;li&gt;Задать новое количество используемых агентов восстановления; &lt;/li&gt;

  &lt;li&gt;Перезапустить службу CA. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Первый этап у нас уже пройден, поскольку у нас уже есть такой массив в AD. Если сертификата агента восстановления нет в AD, то можно его получить из файла:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$cert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;System.Security.Cryptography.X509Certificates.X509Certificate2&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.&lt;/span&gt;&lt;span style="color: #8b4513"&gt;Import&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;.\desktop\kra.cer&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.&lt;/span&gt;&lt;span style="color: #8b4513"&gt;RawData&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;и переменная $bytes будет содержать такой же байтовый массив.&lt;/p&gt;

&lt;p&gt;А вот с конвертером чуть сложнее. Я не нашёл ни одного готового конвертера, который бы выполнял все шаги из пункта 2, поэтому я написал свой конвертер с блек-джеком и шлюхами:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #0000ff"&gt;function&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;ConvertTo-DERstring&lt;/span&gt;&lt;span style="color: #000000"&gt; ([&lt;/span&gt;&lt;span style="color: #008080"&gt;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[]]&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes&lt;/span&gt;&lt;span style="color: #000000"&gt;) {
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; создаём объект StringBuilder, который нам будет собирать конечную символьную строку&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$SB&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;New-Object&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;System.Text.StringBuilder&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; преобразовываем каждый байт в его hex значение&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes1&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes&lt;/span&gt;&lt;span style="color: #000000"&gt; | &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;%&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;{0:X2}&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-f&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; циклом перебираем каждую пару байт&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;for&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$n&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;; &lt;/span&gt;&lt;span style="color: #800080"&gt;$n&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-lt&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes1&lt;/span&gt;&lt;span style="color: #000000"&gt;.count; &lt;/span&gt;&lt;span style="color: #800080"&gt;$n&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$n&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;+&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;2&lt;/span&gt;&lt;span style="color: #000000"&gt;) {
        &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; переставляем элементы пары местами, чтобы получить little-endian hex-строку&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;        &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; после чего получаем десятичное представление этой строки и получаем Unicode&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;        &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; символ, который соответствует этому десятичному значению.&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #000000"&gt;        [&lt;/span&gt;&lt;span style="color: #008080"&gt;void&lt;/span&gt;&lt;span style="color: #000000"&gt;]&lt;/span&gt;&lt;span style="color: #800080"&gt;$SB&lt;/span&gt;&lt;span style="color: #000000"&gt;.Append([&lt;/span&gt;&lt;span style="color: #008080"&gt;char&lt;/span&gt;&lt;span style="color: #000000"&gt;](&lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Invoke-Expression&lt;/span&gt;&lt;span style="color: #000000"&gt; 0x$((&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes1&lt;/span&gt;&lt;span style="color: #000000"&gt;[&lt;/span&gt;&lt;span style="color: #800080"&gt;$n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;+&lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;]) &lt;/span&gt;&lt;span style="color: #ff0000"&gt;+&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes1&lt;/span&gt;&lt;span style="color: #000000"&gt;[&lt;/span&gt;&lt;span style="color: #800080"&gt;$n&lt;/span&gt;&lt;span style="color: #000000"&gt;]))))
    }
    &lt;/span&gt;&lt;span style="color: #800080"&gt;$SB&lt;/span&gt;&lt;span style="color: #000000"&gt;.ToString()
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;А дальше уже по накатанной дороге:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;[Administrator] # создаём COM объект ICertAdmin2
[Administrator] $CertAdmin = new-object -com certificateauthority.admin.1
[Administrator] # выбираем все Enterprise CA
[Administrator] $ldap = [ADSI]&amp;quot;LDAP://CN=KRA, CN=Public Key Services, CN=Services, CN=Configuration, DC=contoso,dc=com&amp;quot;
[Administrator] $kra = $ldap.psbase.children | %{$_}
[Administrator] # сразу конвертируем все сертификаты в DER-encoded string
[Administrator] $kra1 = ConvertTo-DERstring $kra[1].usercertificate[0]
[Administrator] $kra2 = ConvertTo-DERstring $kra[1].usercertificate[1]
[Administrator] # можем убедиться на месте, что строка имеет ожидаемый вид
[Administrator] $kra2
?????A???E  ?????c?♣??????????????????T???????????????????????????????????????T????????????????????????????????????????
??ca♣??????☺????????????????????????????K?????????????????????????????????????????????т????????????????????????????????
??????????????????????☺????????Є?????????????????☻???????☻??????????????ЎЖ?????????????CA??????Ё????????????h??A???????
??????????????????????????????????????????????╣????????????????????????????????????????????????????????????????????????
?????????????????????C?cЁ??????C???????????????????????????????????????????????????????????????????????????????????????
???????????????????????????????????????Х???CA?????Ё???????CA?????Б????CA??????????????????????a???☺????????????????????
????????????????????????????????????????????????????????????????????????????????????????????????????????????
[Administrator] # и записываем первую строку сертификат агента восстанвовления в нулевой индекс
[Administrator] $CertAdmin.SetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x1a,0,3,$kra1)
[Administrator] # все последующие строки сертификатов записываются в последующие индексы массива
[Administrator] $CertAdmin.SetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x1a,1,3,$kra2)
[Administrator] # используем PropID = KRACERTUSEDCOUNT (0x18), чтобы сказать сколько у нас будет использоваться агентов
[Administrator] # я буду их использовать все
[Administrator] $CertAdmin.SetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x18,0,1,2)
[Administrator] # перезапускаем службу CertSvc
[Administrator] $wmi = gwmi win32_service -comp dc2 -filter &amp;quot;name='certsvc'&amp;quot;
[Administrator] [void]$wmi.StopService()
[Administrator] [void]$wmi.StartService()
[Administrator] # и проверяем нашу работу:
[Administrator] $CertReq = new-object -com certificateauthority.request.1
[Administrator] $CertReq.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x18,0,1,0)
2
[Administrator] $CertReq.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x19,0,1,0)
2
[Administrator]&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;всё.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=eabb97f4-c14f-41ef-bc4c-c3df83ecd98f"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,eabb97f4-c14f-41ef-bc4c-c3df83ecd98f.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / CryptoAPI</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=26d5addd-f057-4e3f-8a71-a4ed0f01a836</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=26d5addd-f057-4e3f-8a71-a4ed0f01a836</wfw:commentRss>
      <title>CryptoAPI и управление Certification Authority с помощью PowerShell (часть 3)</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx</link>
      <pubDate>Mon, 16 Nov 2009 16:04:48 GMT</pubDate>
      <description>&lt;div&gt;&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Update 05.12.2009:&lt;/FONT&gt;&lt;/STRONG&gt; разработчики подтвердили баг в ICertAdmin2 интерфейсе. Проблема заключается&amp;nbsp;в том, что после первого запроса указанных PropID они кешируются и при смене контекста конфигурации (Certification Authority), этот кеш не очищается.&lt;/P&gt;
&lt;HR&gt;

&lt;P&gt;Прежде чем продолжать исследование CryptoAPI COM интерфейсов, предлагаю посмотреть несколько полезных ссылок и поговорить о багах в интерфейсе &lt;STRONG&gt;ICertAdmin2&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;При использовании интерфейса ICertAdmin2, ICertRequest2D (этот интерфейс мы ещё посмотрим в будущих постах) мы используем различные аргументы для получения свойст CA с использованием метода &lt;STRONG&gt;GetCAProerty()&lt;/STRONG&gt;. И вот их где мы можем получить числовые значения этих аргументов:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;PropID&lt;/STRONG&gt; и &lt;STRONG&gt;PropType&lt;/STRONG&gt; — &lt;A href="http://msdn.microsoft.com/en-us/library/cc249749(PROT.10).aspx" target=_blank&gt;&lt;STRONG&gt;3.2.1.4.3.2 ICertRequestD2::GetCAProperty (Opnum 7)&lt;/STRONG&gt;&lt;/A&gt; 
&lt;LI&gt;&lt;STRONG&gt;Flags&lt;/STRONG&gt; — &lt;A href="http://msdn.microsoft.com/en-us/library/aa374936(VS.85).aspx" target=_blank&gt;&lt;STRONG&gt;EncodingType Enumeration&lt;/STRONG&gt;&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;А теперь поговорим о багах. Как выяснилось, &lt;STRONG&gt;ICertAdmin2::GetCAProperty()&lt;/STRONG&gt;, который определён в библиотеке &lt;EM&gt;certadm.dll&lt;/EM&gt; имеет баги с PropID, которые связаны с количественной информацией. Будь то количество сертификатов CA, количество агентов восстановления ключей (&lt;STRONG&gt;Key Recovery Agents&lt;/STRONG&gt;) и т.д. И вот в чём это выражается:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;DC1&lt;/STRONG&gt; — корневой CA с именем Contoso CA. Имеет 2 сертификата CA и одного назначенного агента восстановления; 
&lt;LI&gt;&lt;STRONG&gt;DC2&lt;/STRONG&gt; — подчинённый CA с именем Contoso-DC2-CA. Имеет 1 сертификат CA и ни одного назначенного агента восстановления. &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Мы будем получать данные как с локального CA, так и с удалённого CA запуская код с каждого сервера. Кратко об используемых PropID:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;0x0B&lt;/STRONG&gt; — количество сертификатов CA; 
&lt;LI&gt;&lt;STRONG&gt;0x19&lt;/STRONG&gt; — общее количество агентов восстановления на CA; 
&lt;LI&gt;&lt;STRONG&gt;0x18&lt;/STRONG&gt; — общее количество используемых агентов восстановления; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;И вот какие результаты мы видим, когда собираем эти свойства с сервера &lt;STRONG&gt;DC1&lt;/STRONG&gt;:&lt;/P&gt;
&lt;DIV style="WIDTH: 935px"&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE style="BACKGROUND-COLOR: #000040; FONT: 9pt consolas, lucida console"&gt;&lt;FONT color=#c0c0c0&gt;&lt;SPAN&gt;&lt;P&gt;[Administrator] # создаём COM объек:
[Administrator] $CertAdmin = New-Object -com CertificateAuthority.Admin.1
[Administrator] # получаем список сертификатов CA на локальном серве
[Administrator] # мы видим 2 сертификата, как положено
[Administrator] $certadmin.GetCAProperty("dc1\contoso ca",0xb,0,1,0)
2
[Administrator] # и он то же самое показывает и для удалённого сервера, хотя там всего 1 сертификат
[Administrator] $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0)
2
[Administrator] # ладно, смотрим, сколько всего KRA у нас на локальном сервере. Их 1, как на самом деле
[Administrator] $certadmin.GetCAProperty("dc1\contoso ca",0x19,0,1,0)
1
[Administrator] # используемых сертификатов тоже 1.
[Administrator] $certadmin.GetCAProperty("dc1\contoso ca",0x18,0,1,0)
1
[Administrator] # как я уже говорил, на DC2 нет агентов восстановления, хотя метод показывает их по одному в обоих случаях
[Administrator] $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0x19,0,1,0)
1
[Administrator] $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0x18,0,1,0)
1
[Administrator]&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;/DIV&gt;
&lt;P&gt;собираем ту же информацию, запуская код с сервера &lt;STRONG&gt;DC2&lt;/STRONG&gt;:&lt;/P&gt;
&lt;DIV style="WIDTH: 935px"&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE style="BACKGROUND-COLOR: #000040; FONT: 9pt consolas, lucida console"&gt;&lt;FONT color=#c0c0c0&gt;&lt;SPAN&gt;&lt;P&gt;PS C:\&amp;gt; # создаём COM объект:
PS C:\&amp;gt; $CertAdmin = New-Object -com CertificateAuthority.Admin.1
PS C:\&amp;gt; # получаем список сертификатов CA с локального сервера.
PS C:\&amp;gt; # их мы видим ровно 1, как и должно быть
PS C:\&amp;gt; $certadmin.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0)
1
PS C:\&amp;gt; # в предыдущем примере мы видели, что на DC1 2 сертификата CA.
PS C:\&amp;gt; # проверим, так ли это?
PS C:\&amp;gt; $certadmin.GetCAProperty("dc1\contoso ca",0xb,0,1,0)
1
PS C:\&amp;gt; # wow! обломс, метод возвращает тоже 1. А сколько у нас агентов восстановления?
PS C:\&amp;gt; # и снова облом. На сервере DC1 нет агентов восстановления (хотя предыдущий пример говорит об обратном):
PS C:\&amp;gt; $certadmin.GetCAProperty("dc1\contoso ca",0x19,0,1,0)
0
PS C:\&amp;gt; $certadmin.GetCAProperty("dc1\contoso ca",0x18,0,1,0)
0&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;/DIV&gt;
&lt;P&gt;а теперь посмотрим на результаты с использованием того же метода и тех же PropID, но с использованием интерфейса ICertRequest, который определён в библиотеке &lt;EM&gt;certcli.dll&lt;/EM&gt;. Те же тесты уже возвращают правильные результаты:&lt;/P&gt;
&lt;P&gt;с &lt;STRONG&gt;DC1&lt;/STRONG&gt;:&lt;/P&gt;
&lt;DIV style="WIDTH: 935px"&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE style="BACKGROUND-COLOR: #000040; FONT: 9pt consolas, lucida console"&gt;&lt;FONT color=#c0c0c0&gt;&lt;SPAN&gt;&lt;P&gt;[Administrator] $request = New-Object -com CertificateAuthority.Request.1
[Administrator] $request.GetCAProperty("dc1\contoso ca",0xb,0,1,0)
2
[Administrator] $request.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0)
1
[Administrator] $request.GetCAProperty("dc1\contoso ca",0x19,0,1,0)
1
[Administrator] $request.GetCAProperty("dc1\contoso ca",0x18,0,1,0)
1
[Administrator] $request.GetCAProperty("dc2\contoso-dc2-ca",0x19,0,1,0)
0
[Administrator] $request.GetCAProperty("dc2\contoso-dc2-ca",0x18,0,1,0)
0
[Administrator]&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;/DIV&gt;
&lt;P&gt;с &lt;STRONG&gt;DC2&lt;/STRONG&gt;:&lt;/P&gt;
&lt;DIV style="WIDTH: 935px"&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE style="BACKGROUND-COLOR: #000040; FONT: 9pt consolas, lucida console"&gt;&lt;FONT color=#c0c0c0&gt;&lt;SPAN&gt;&lt;P&gt;PS C:\&amp;gt; $request = New-Object -com CertificateAuthority.Request.1
PS C:\&amp;gt; $request.GetCAProperty("dc2\contoso-dc2-ca",0xb,0,1,0)
1
PS C:\&amp;gt; $request.GetCAProperty("dc1\contoso ca",0xb,0,1,0)
2
PS C:\&amp;gt; $request.GetCAProperty("dc1\contoso ca",0x19,0,1,0)
1
PS C:\&amp;gt; $request.GetCAProperty("dc1\contoso ca",0x18,0,1,0)
1
PS C:\&amp;gt; $request.GetCAProperty("dc2\contoso-dc2-ca",0x19,0,1,0)
0
PS C:\&amp;gt; $request.GetCAProperty("dc2\contoso-dc2-ca",0x18,0,1,0)
0
PS C:\&amp;gt;&lt;/P&gt;&lt;/SPAN&gt;&lt;/FONT&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;&lt;/DIV&gt;
&lt;P&gt;Поэтому следует с осторожностью относиться к выводу &lt;STRONG&gt;ICertAdmin2::GetCAProperty()&lt;/STRONG&gt;, а ещё лучше — использовать этот метод, который реализован в интерфейсе &lt;A href="http://msdn.microsoft.com/en-us/library/aa385043(VS.85).aspx" target=_blank&gt;&lt;STRONG&gt;ICertRequest::GetCAProperty()&lt;/STRONG&gt;&lt;/A&gt;. Чем это вызвано я пока не знаю, но задал я задал вопрос нужным людям, поэтому я дам знать в случае ответа на вопрос.&lt;/P&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=26d5addd-f057-4e3f-8a71-a4ed0f01a836"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,26d5addd-f057-4e3f-8a71-a4ed0f01a836.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / CryptoAPI</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=ca3a2177-92b3-46af-bc7b-0497cdbce74e</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,ca3a2177-92b3-46af-bc7b-0497cdbce74e.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,ca3a2177-92b3-46af-bc7b-0497cdbce74e.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=ca3a2177-92b3-46af-bc7b-0497cdbce74e</wfw:commentRss>
      <title>CryptoAPI и управление Certification Authority с помощью PowerShell (часть 2)</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,ca3a2177-92b3-46af-bc7b-0497cdbce74e.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,ca3a2177-92b3-46af-bc7b-0497cdbce74e.aspx</link>
      <pubDate>Tue, 10 Nov 2009 16:04:48 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;В &lt;a href="http://www.sysadmins.lv/PermaLink,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx"&gt;&lt;strong&gt;первой части&lt;/strong&gt;&lt;/a&gt; управления Certification Authority (CA) мы рассмотрели метод &lt;a href="http://msdn.microsoft.com/en-us/library/aa383238(VS.85).aspx"&gt;&lt;strong&gt;GetCAProperty&lt;/strong&gt;&lt;/a&gt;, при помощи которого мы можем получать различные сведения про сервер CA. Сегодня мы посмотрим ещё несколько интересных моментов, которые будут связаны с CRL и опять будет немного треша с CryptoAPI, а именно:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;Получение статуса публикации CRL; &lt;/li&gt;    &lt;li&gt;Получение Base и Delta CRL из CA в виде файлов; &lt;/li&gt;    &lt;li&gt;Отзыв сертификатов; &lt;/li&gt;    &lt;li&gt;Извлечение сертификатов из CRL; &lt;/li&gt;    &lt;li&gt;Публикация новых CRL. &lt;/li&gt; &lt;/ul&gt;  &lt;h1 align="center"&gt;Начало работы&lt;/h1&gt;  &lt;p&gt;Для начала мы должны будем создать &lt;a href="http://msdn.microsoft.com/en-us/library/aa383234(VS.85).aspx"&gt;&lt;strong&gt;ICertAdmin2&lt;/strong&gt;&lt;/a&gt; COM объект для управления CA, который будет использоваться нами для всех сегодняшних операций:&lt;/p&gt;  &lt;div style="width: 935px"&gt;   &lt;blockquote&gt;     &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $CertAdmin = New-Object -ComObject &amp;quot;CertificateAuthority.Admin.1&amp;quot;
&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;h1 align="center"&gt;Получение Base и Delta CRL из CA в виде файлов&lt;/h1&gt;

&lt;p&gt;Далее мы должны узнать PropID, который бы отвечал за показ CRL вот по этой ссылке: &lt;a href="http://msdn.microsoft.com/en-us/library/cc249749(PROT.10).aspx"&gt;&lt;strong&gt;3.2.1.4.2.2 ICertRequestD2::GetCAProperty (Opnum 7)&lt;/strong&gt;&lt;/a&gt;. Нас будет интересовать 2 этих ID: &lt;strong&gt;CR_PROP_BASECRL (0x11)&lt;/strong&gt; и &lt;strong&gt;CR_PROP_DELTACRL (0x12)&lt;/strong&gt;. Поскольку тип возвращаемых данных будет &lt;strong&gt;Binary&lt;/strong&gt;, то &lt;strong&gt;PropType&lt;/strong&gt; будет равен 3, а &lt;strong&gt;Flags&lt;/strong&gt; выставим в 0 (Base64CRLHeader). Можно и другой указать, от этого только зависит метод записи в файл.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; напоминаю, что индекс &lt;strong&gt;PropType&lt;/strong&gt; начинается с 1, а &lt;strong&gt;Flags&lt;/strong&gt; с 0 и их возможные значения описаны здесь: &lt;a href="http://msdn.microsoft.com/en-us/library/aa383238(VS.85).aspx"&gt;&lt;strong&gt;GetCAProperty&lt;/strong&gt;&lt;/a&gt;. А так же то, что в Flags первые 2 значения перепутаны местами на MSDN.&lt;/p&gt;

&lt;p&gt;И вот как мы их можем получить:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $BaseCRL =  $certadmin.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x11,0,3,0)
PS C:\&amp;gt; $BaseCRL
-----BEGIN X509 CRL-----
MIIEDTCCAvUCAQEwDQYJKoZIhvcNAQEFBQAwRzETMBEGCgmSJomT8ixkARkWA2Nv
bTEXMBUGCgmSJomT8ixkARkWB2NvbnRvc28xFzAVBgNVBAMTDmNvbnRvc28tREMy
LUNBFw0wOTExMDkwNjI0NDlaFw0wOTExMTcwNjQ0NDlaMIIBzDAbAgpG7E9iAAAA
AACSFw0wOTExMDgxODM5MDBaMCkCCm716aoAAAAAAI8XDTA5MTAyMjE2MjI1OVow
DDAKBgNVHRUEAwoBBDAbAgpxOBcQAAAAAACLFw0wOTA5MjgwNjMzMDBaMBsCCl6/
ZbYAAAAAAIkXDTA5MDkyNDE3MTcwMFowGwIKXnVZiQAAAAAAiBcNMDkwOTI0MTUw
MjAwWjApAgoggMu3AAAAAAAVFw0wOTA1MTcyMDE0MDBaMAwwCgYDVR0VBAMKAQUw
KQIKYRZ2nAAAAAAADRcNMDkwNTAxMTk1MzAwWjAMMAoGA1UdFQQDCgEFMCkCCmJ0
33IAAAAAAAoXDTA5MDQxOTEzMDUwMFowDDAKBgNVHRUEAwoBBDApAgphINAVAAAA
AAAHFw0wOTAzMzExMTEzMDBaMAwwCgYDVR0VBAMKAQUwKQIKYRT3zAAAAAAABhcN
MDkwMzMxMTAzMTAwWjAMMAoGA1UdFQQDCgEFMCkCCmERwOwAAAAAAAUXDTA5MDMz
MTEwMTgwMFowDDAKBgNVHRUEAwoBBDApAgphDxXgAAAAAAAEFw0wOTAzMzExMDE0
MDBaMAwwCgYDVR0VBAMKAQSggakwgaYwHwYDVR0jBBgwFoAUZiAsZ5wOPk1F8vmX
BZdmE1QTJjYwEAYJKwYBBAGCNxUBBAMCAQAwCwYDVR0UBAQCAgDyMBwGCSsGAQQB
gjcVBAQPFw0wOTExMTYwNjM0NDlaMEYGA1UdLgQ/MD0wO6A5oDeGNWh0dHA6Ly9k
YzIuY29udG9zby5jb20vQ2VydEVucm9sbC9jb250b3NvLURDMi1DQSsuY3JsMA0G
CSqGSIb3DQEBBQUAA4IBAQCCNVxtZbAbB5C1bI5Z6PF+Eph2MaRhl9pv0FjYhH/j
Xlvffau1m5bW72No7FC2k8FFU2oHFSZvAVNKgjm6+ECb4iEpzREcHpwsot1TG0kn
Pv+DRGjQ2ndes8OM11v3oYUJxlNOMqY6q03lj/BEJb+ocNerWRay8G0sycy1ABCD
/UPvP9qq54WvwQnJyV5bZJcJG3WYtN7zkZZzf5MR3v+c4OODLiLw5pXgku49USFu
kTuEh5DYcF5zbo6h5IqAW+OP6iMFepxkUEZUb/5VOYK8VcpXDwMzIRzlf+bITHyX
6PVugwm6TXkn9eVrAfJUd70S9LV7XVTz32IykC3tNXFY
-----END X509 CRL-----


PS C:\&amp;gt; $DeltaCRL =  $certadmin.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x12,0,3,0)
PS C:\&amp;gt; $BaseCRL &amp;gt; base.crl
PS C:\&amp;gt; $DeltaCRL &amp;gt; delta.crl
PS C:\&amp;gt; &amp;amp; .\base.crl
PS C:\&amp;gt; &amp;amp; .\delta.crl
PS C:\&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;последние 2 команды просто запускают эти CRL файлы. К сожалению не существует ни одного родного класса, который бы представлял собой объект CRL, поэтому как-то разбирать его на таком уровне пока не представляется возможным. Хотя существуют сторонние библиотеки (например, в Mono есть класс X509CRL).&lt;/p&gt;

&lt;h1 align="center"&gt;Получение статуса публикации CRL&lt;/h1&gt;

&lt;p&gt;Но мы можем кое что узнать о статусе наших CRL. Для этого существует PropID = &lt;strong&gt;CR_PROP_CRLSTATE (0x14)&lt;/strong&gt;. Тип возвращаемых данных будет Long, значит PropType будет 1, а Flags будет игнорироваться, поэтому поставим его в 0:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $certadmin.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x14,0,1,0)
3&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Расшифровку этого значения можно найти здесь:&amp;#160; &lt;a href="http://msdn.microsoft.com/en-us/library/cc249794(PROT.10).aspx" target="_blank"&gt;&lt;strong&gt;3.2.1.4.2.2.20 PropID = 0x00000014 (CR_PROP_CRLSTATE) &amp;quot;CA CRL State&amp;quot;&lt;/strong&gt;&lt;/a&gt;. Число 3 означает, что с CRL у нас всё хорошо (&lt;strong&gt;CA_DISP_VALID (0x03)&lt;/strong&gt;). В принципе, на данном этапе нам больше ничего и не нужно. Но мы можем посмотреть более детальные сведения по каждому типу CRL. Для получения более детальной ошибки мы должны использовать следующие PropID:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CR_PROP_BASECRLPUBLISHSTATUS (0x1E) &lt;/strong&gt;&lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;CR_PROP_DELTACRLPUBLISHSTATUS (0x1F)&lt;/strong&gt; &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Для этих PropID тип данных так же указан Long, поэтому PropType выставим в 1, а Flags в 0:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $certadmin.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x1E,0,1,0)
5
PS C:\&amp;gt; $certadmin.GetCAProperty(&amp;quot;dc2\contoso-dc2-ca&amp;quot;,0x1F,0,1,0)
6
PS C:\&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Мы получили число 5 для BaseCRL и 6 для DeltaCRL. Расшифровку этих значений можно посмотреть вот здесь: &lt;a href="http://msdn.microsoft.com/en-us/library/cc249804(PROT.10).aspx" target="_blank"&gt;&lt;strong&gt;3.2.1.4.2.2.30 PropID = 0x0000001E (CR_PROP_BASECRLPUBLISHSTATUS) &amp;quot;Base CRL Publishing Status&amp;quot;&lt;/strong&gt;&lt;/a&gt;. Поскольку вывод — не конкретное число, а результат двоичного оператора И (AND), то мы это число должны разбить на составляющие. И вот как это делается:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$Return&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$certadmin&lt;/span&gt;&lt;span style="color: #000000"&gt;.GetCAProperty(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;ServerName\CA Name&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0x1E&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #800080"&gt;$options&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;2&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;8&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;16&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;32&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;64&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;128&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;256&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;512&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;1024&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;2048&lt;/span&gt;&lt;span style="color: #000000"&gt; | &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;%&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #800080"&gt;$Return&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-band&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;} | ?{&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;}
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; поскольку значения масок являются результаты возведения двойки в степень&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; начиная от 0 до 11, то эту строчку можно переписать более готично.&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Напоминаю, что возведение любого числа в нулевую степень&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; всегда вернёт 1. Кажется, это из алгебры 5-6 класса.&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$options&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;.&lt;/span&gt;&lt;span style="color: #000000"&gt;.11&lt;/span&gt;&lt;span style="color: #000000"&gt;| &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;%&lt;/span&gt;&lt;span style="color: #000000"&gt;{[&lt;/span&gt;&lt;span style="color: #008080"&gt;Math&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;Pow&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #000000"&gt;2&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;)} | &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;%&lt;/span&gt;&lt;span style="color: #000000"&gt;{&lt;/span&gt;&lt;span style="color: #800080"&gt;$Return&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-band&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;} | ?{&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;}
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;switch&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$options&lt;/span&gt;&lt;span style="color: #000000"&gt;) {
    &lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The CRL is a base CRL&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;2&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The CRL is a delta CRL&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The last CRL publication that was completed and published to the locations specified in the CA&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;8&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The CRL is a shadow delta CRL&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;16&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The CA MAY publish the CRL to a local store that is not externally accessible.
        This error is returned when publishing to this intermediate store failed&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;32&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;An error occurred during publication of the CRL.
        The error indicates that the file schema cannot be recognized.The schema must be file: or ldap:&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;64&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;Publication of the CRL was manually initiated by an administrator&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;128&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;A CRL signature error was detected. The CSP was not correct&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;256&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;An error occurred during publication of the CRL to an LDAP URL&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;512&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;An error occurred during publication of the CRL to a file URL&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;1024&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;An error occurred during publication of the CRL to an FTP URL. FTP URLs are not supported&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    &lt;/span&gt;&lt;span style="color: #000000"&gt;2048&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;The CA cannot publish CRLs to HTTP URLs. This error is returned if a CA administrator
        configured the CA to publish CRLs to HTTP URLs&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;}
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Следовательно число 5 (1+4) говорит нам о том, что это был Base CRL и он был опубликован успешно. А 6 (2+4) — Delta CRL был опубликован успешно.&lt;/p&gt;

&lt;h1 align="center"&gt;Отзыв сертификатов&lt;/h1&gt;

&lt;p&gt;Интерфейс IcertAdmin2 позволяет нам отзывать сертификаты на сервере CA. Для этого мы воспользуемся методом &lt;a href="http://msdn.microsoft.com/en-us/library/aa383251(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;RevokeCertificate()&lt;/strong&gt;&lt;/a&gt;. Метод достаточно простой и примерная команда для отзыва сертификата будет выглядеть так:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt;.RevokeCertificate(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;ServerName\CA Name&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;0123456789&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;4&lt;/span&gt;&lt;span style="color: #000000"&gt;,(&lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Get-Date&lt;/span&gt;&lt;span style="color: #000000"&gt;).AddDays(&lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;))&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;strong&gt;0123456789&lt;/strong&gt; будет обозначать серийный номер сертификата, &lt;strong&gt;4&lt;/strong&gt; — причина отзыва будет Superseded и эффективная дата отзыва (когда сертификат будет помещён в Revoked Certificates) будет 24 часа после выполнения команды. Да, именно этим методом можно отзывать корневые сертификаты &lt;img alt=":)" src="/smilies/happy.gif"&gt;.&lt;/p&gt;

&lt;h1 align="center"&gt;Извлечение сертификатов из CRL&lt;/h1&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; хоть Microsoft и поддерживает извлечение сертификатов из CRL (отмена статуса Revoked), этой возможностью не следует пользоваться в силу определённых причин, как невозможность определеления в какое время сертификат был помещён и извлечён из CRL.&lt;/p&gt;

&lt;p&gt;Если сертификат был отозван со статусом Certificate Hold (6), то его можно в любое время вернуть обратно. Для всех остальных типов отзыва такая возможность не поддерживается. Для отмены статуса Revoked нужно использовать этот же метод, только в качестве причины отзыва указать значение MAX_DWORD, которое является &lt;strong&gt;0xffffffff&lt;/strong&gt; или просто &lt;strong&gt;–1&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt;.RevokeCertificate(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;ServerName\CA Name&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #000000"&gt;0123456789&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #ff0000"&gt;-&lt;/span&gt;&lt;span style="color: #000000"&gt;1&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;h1 align="center"&gt;Публикация новых CRL&lt;/h1&gt;

&lt;p&gt;Если вы хотите опубликовать новые CRL вручную (т.е. в промежутке между плановой публикацией CRL), то мы должны воспользоваться методом &lt;a href="http://msdn.microsoft.com/en-us/library/aa383249(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;PublishCRLs()&lt;/strong&gt;&lt;/a&gt;. Его синтаксис достаточно простой:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$CertAdmin&lt;/span&gt;&lt;span style="color: #000000"&gt;.PublishCRLs(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;ServerName\CA Name&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;,&lt;/span&gt;&lt;span style="color: #000000"&gt;0&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Эта команда переопубликует как основной, так и инкрементальный CRL (при публикации Base CRL инкрементальный CRL публикуется всегда, потому что Effective Date у него не может быть меньше, чем у Base CRL). Что касается последнего аргумента, то он бывает ещё полезен, если по каким-то причинам потерялся какой-то файл CRL. Тогда вы можете выставить CRLFlags в 4 (0x4) и тогда CA переопубликует текущие CRL без обновления их содержимого и дат.&lt;/p&gt;

&lt;p&gt;На сегодня это всё.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=ca3a2177-92b3-46af-bc7b-0497cdbce74e"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,ca3a2177-92b3-46af-bc7b-0497cdbce74e.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / CryptoAPI</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=1cec0947-9113-4de2-bf48-809a09849f4c</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=1cec0947-9113-4de2-bf48-809a09849f4c</wfw:commentRss>
      <title>CryptoAPI и управление Certification Authority с помощью PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx</link>
      <pubDate>Thu, 05 Nov 2009 20:22:36 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Продолжая тему криптографии, предлагаю несколько ближайших постов посвятить вопросам использования CryptoAPI в PowerShell для управления &lt;strong&gt;Cerficiation Authority&lt;/strong&gt; (сокращённо &lt;strong&gt;CA&lt;/strong&gt;). Я считаю эту тему достаточно интересной, хоть у нас есть космическая утилита certutil.exe. Но тот, кто видел хелп к нему, тот знает какой это ужас, автоматизировать что-то с использованием certutil. Microsoft подарил нам не менее космический и православный инструмент автоматизации — PowerShell. К сожалению, вынужден признать, что в ряде задач PowerShell сильно уступает аналогам в cmd и с этим ничего нельзя поделать. Но по мере своих сил буду пытаться доказывать обратное. Одно из преимуществ PowerShell является поддержка .NET, который очень удобен в использовании. Но .NET не всемогущ и не содержит в себе ни единого класса, при помощи которого можно было бы управлять службой certificate services (точнее самим CA). CryptoAPI неплохо документированы на уровне unmanaged code (а это подразумевает использование низкоуровневых языков программирования, как C++). Но, опять, слава &lt;strike&gt;сиськамСноверу&lt;/strike&gt;Протоколу у нас есть одна лазейка — COM интерфейсы к CryptoAPI. Изучив немного эти интерфейсы, обнаружил, что они местами очень интересные и досточно легко управляемы. Но это не всегда так, иногда они бывают достаточно сложными для понимания с первого раза. В процессе исследования, были обнаружены вообще нелогичные вещи, с которыми нам придётся считаться.&lt;/p&gt;  &lt;p&gt;Эти COM интерфейсы позволили мне реализовать едва ли не половину функционала моего PowerPack'а для PowerGUI. Оценить моё детище можно по этой ссылке: &lt;a href="http://powergui.org/entry.jspa?externalID=2552&amp;amp;categoryID=21" target="_blank"&gt;&lt;strong&gt;Enterprise PKI management&lt;/strong&gt;&lt;/a&gt;. Я в него вложил достаточно много знаний для того, чтобы упростить жизнь администраторам инфраструктур PKI. Пока прогресс неважный, т.к. я пока только повторяю функционал консолей certmgr.msc, certsrv.msc, ocsp.msc и certutil.exe. Но я надеюсь реализовать там действительно что-то нужное и очень полезное.&lt;/p&gt;  &lt;p&gt;Наша отправная точка на MSDN будет находиться здесь: &lt;a href="http://msdn.microsoft.com/en-us/library/aa380253(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;Cryptography Interfaces&lt;/strong&gt;&lt;/a&gt;. Для начала мы поработаем с интерфейсом &lt;a href="http://msdn.microsoft.com/en-us/library/aa383234(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;ICertAdmin2&lt;/strong&gt;&lt;/a&gt;, который зарегистрирован в системе как COM класс &lt;strong&gt;CertificateAuthority.Admin.1&lt;/strong&gt;. Вот как он создаётся:&lt;/p&gt;  &lt;div style="width: 935px"&gt;   &lt;blockquote&gt;     &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $CertAdmin = New-Object -ComObject &amp;quot;CertificateAuthority.Admin.1&amp;quot;
PS C:\&amp;gt; $CertAdmin | gm


   TypeName: System.__ComObject#{f7c3ac41-b8ce-4fb4-aa58-3d1dc0e36b39}

Name                     MemberType Definition
----                     ---------- ----------
DeleteRow                Method     int DeleteRow (string, int, Date, int, int)
DenyRequest              Method     void DenyRequest (string, int)
GetArchivedKey           Method     string GetArchivedKey (string, int, int)
GetCAProperty            Method     Variant GetCAProperty (string, int, int, int, int)
GetCAPropertyDisplayName Method     string GetCAPropertyDisplayName (string, int)
GetCAPropertyFlags       Method     int GetCAPropertyFlags (string, int)
GetConfigEntry           Method     Variant GetConfigEntry (string, string, string)
GetCRL                   Method     string GetCRL (string, int)
GetMyRoles               Method     int GetMyRoles (string)
GetRevocationReason      Method     int GetRevocationReason ()
ImportCertificate        Method     int ImportCertificate (string, string, int)
ImportKey                Method     void ImportKey (string, int, string, int, string)
IsValidCertificate       Method     int IsValidCertificate (string, string)
PublishCRL               Method     void PublishCRL (string, Date)
PublishCRLs              Method     void PublishCRLs (string, Date, int)
ResubmitRequest          Method     int ResubmitRequest (string, int)
RevokeCertificate        Method     void RevokeCertificate (string, string, int, Date)
SetCAProperty            Method     void SetCAProperty (string, int, int, int, Variant)
SetCertificateExtension  Method     void SetCertificateExtension (string, int, string, int, int, Variant)
SetConfigEntry           Method     void SetConfigEntry (string, string, string, Variant)
SetRequestAttributes     Method     void SetRequestAttributes (string, int, string)


PS C:\&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Как вы видите, этот интерфейс позволяет использовать достаточно много интересных методов. Давайте начнём с простого (а может быть и не очень простого) — &lt;a href="http://msdn.microsoft.com/en-us/library/aa383238(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;GetCAProperty&lt;/strong&gt;&lt;/a&gt;. По ссылке вообще ничего непонятно, что и как там использовать. Единственное, что я понял — это то, что данный метод принимает 5 параметров в определённом порядке и всё. Поэтому давайте будем считать, что этой странички не существует в природе (кроме случаев, когда будем преследовать порядок расположения аргументов). Пошарившись на MSDN, нашёл более годную ссылку в спецификациях &lt;strong&gt;Windows Communications Protocols&lt;/strong&gt; — &lt;a href="http://msdn.microsoft.com/en-us/library/cc249749(PROT.10).aspx" target="_blank"&gt;&lt;strong&gt;3.2.1.4.2.2 ICertRequestD2::GetCAProperty (Opnum 7)&lt;/strong&gt;&lt;/a&gt;. И вот как должны выглядеть параметры:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;strConfig&lt;/strong&gt; — имя компьютера и сервера CA в формате &lt;font color="#0000ff"&gt;ComputerName\CAName&lt;/font&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;PropId&lt;/strong&gt; — ID требуемого свойства. Должно указываться в числовом формате (т.к. тип данных указан Long). Это число можно взять из колонки &lt;strong&gt;Numerical Value&lt;/strong&gt; таблички &lt;a href="http://msdn.microsoft.com/en-us/library/cc249749(PROT.10).aspx" target="_blank"&gt;&lt;strong&gt;3.2.1.4.2.2 ICertRequestD2::GetCAProperty (Opnum 7)&lt;/strong&gt;&lt;/a&gt;. Например, для получения DeltaCRL надо указать число &lt;strong&gt;18&lt;/strong&gt; (0x12). &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;PropIndex&lt;/strong&gt; — если свойство индексированное (т.е. содержит несколько искомых объектов), то PropIndex указывает на индекс массива, в котором хранится определённый объект искомого свойства. Например, CA может содержать несколько своих сертификатов. И с использованием PropIndex мы сможем выбирать различные сертификаты, выбирая их из массива. Начало индексирования начинается с нуля. Если свойство неиндексируемое, то это значение будет игнорироваться. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;PropType&lt;/strong&gt; — указываете тип данных, в котором хотите получить конкретное свойство. Во второй таблице уже указаны рекомендованные значения типов данных для каждого набора свойств. Тип данных так же нужно указывать в числовом формате. Однако, &lt;font color="#ff0000"&gt;здесь индекс начинается не с нуля, а с единицы&lt;/font&gt;. Т.е. тип данных &lt;strong&gt;String&lt;/strong&gt; будет иметь значение &lt;strong&gt;4&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;Flags&lt;/strong&gt; — помимо типа возвращаемых данных нам нужно указать формат этих данных. Во второй таблице так же приведены рекомендованные (хотя слово MUST и ещё капсом как бы намекает на обязательность. Хотя, это не совсем так. Если вы в первый раз будете этим заниматься, то используйте значения из второй таблички). А вот здесь индекс начинается с нуля. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; по всей видимости в табличке с флагами закралась ошибка, т.к. использование первого флага даёт Base64, но с заголовками Begin/End Certificate. А второй — наоборот, без заголовка.&lt;/p&gt;

&lt;p&gt;Вам кажется, что это всё ужасно и сложно? Поверьте, это не так. Давайте прочитаем парочку свойств. Например, прочитаем ссылки на CRL и CRT, которые публикуются в CDP и AIA издаваемых сертификатах. Исходя из таблички мы знаем, что CRL'ы вызываются &lt;strong&gt;PropID = 0x29&lt;/strong&gt; (или 41 в десятичной нотации), а CRT — &lt;strong&gt;PropID = 0x2A&lt;/strong&gt; (или 42). Поскольку это индексируемое свойство, то первая ссылка будет содержаться в индексе 0 (первый индекс массива), а последующие ссылки в индексах 1 и далее и &lt;strong&gt;PropIndex&lt;/strong&gt; мы укажем &lt;strong&gt;0&lt;/strong&gt;. PropType у нас будет &lt;strong&gt;String&lt;/strong&gt; и числовое значение — 4 (не забываем, что PropType считаются начиная с единицы). &lt;strong&gt;Flags&lt;/strong&gt; может быть любой, т.к. он будет игнорироваться при &lt;strong&gt;PropType = 4&lt;/strong&gt;:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $CertAdmin.GetCAProperty(&amp;quot;ca\sysadmins-lv-ca&amp;quot;, 41, 0, 4, 0)
http://ca.sysadmins.lv/sysadmins-LV-CA.crl

PS C:\&amp;gt; $CertAdmin.GetCAProperty(&amp;quot;ca\sysadmins-lv-ca&amp;quot;, 42, 0, 4, 0)
http://ca.sysadmins.lv/sysadmins-LV-CA.crt

PS C:\&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Как вы видите, на самом деле здесь нет ничего страшного. Нужно лишь научиться оперировать табличкой. Давайте для разнообразия посмотрим на сертификат CA. Для этого мы должны найти PropID, который отвечал за сертификат. Это будет &lt;strong&gt;PropID = 0xC&lt;/strong&gt;. Поскольку этот параметр так же индексируемый, то он будет содержать все сертификаты CA, если их там несколько. Самый первый сертификат будет храниться в индексе 0, следующий сертификат в индексе 1 и т.д. Исходя из таблички, PropType должен быть 3. Посмотрим сертификат в Base64 кодировке, т.е. Flags должен быть 0 или 1:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $cert = $CertAdmin.GetCAProperty(&amp;quot;ca\sysadmins-lv-ca&amp;quot;, 0xc, 0, 3, 0)
PS C:\&amp;gt; $cert
-----BEGIN CERTIFICATE-----
MIIFbTCCA1WgAwIBAgIQPf+vkU1hMoJCe9WRwftYbTANBgkqhkiG9w0BAQUFADBJ
MRIwEAYKCZImiZPyLGQBGRYCbHYxGTAXBgoJkiaJk/IsZAEZFglzeXNhZG1pbnMx
GDAWBgNVBAMTD3N5c2FkbWlucy1MVi1DQTAeFw0wOTA4MDYwNzIxMDFaFw0xNDA4
MDYwNzMwNTRaMEkxEjAQBgoJkiaJk/IsZAEZFgJsdjEZMBcGCgmSJomT8ixkARkW
CXN5c2FkbWluczEYMBYGA1UEAxMPc3lzYWRtaW5zLUxWLUNBMIICIjANBgkqhkiG
9w0BAQEFAAOCAg8AMIICCgKCAgEAwL5wHTMEsMg6yDzqWPd9e/GT856o9OWJrv4Y
9iXtTa5mkdEZsbckVmAJODG28lcI7ScuD0rfceB6/gVn4VMK2SITsOv2XzC3ApRE
zExEIuRmspFlpaDmOvBTYafkzokN2RJ+UQq8M9RSnSBHrOcvNJQYgglbjQOHsg4f
qyMoPoZ+LYjoGZcCtqmR+FMOnalUGohnanf/fQJ/gcoAET6H45rqAB/P90sWOsZo
pwCgGmvJe4GBXbZDg4ADZIbrYm2baxwKJlhsDAhzZ8Fo2irnSBFJavu6+LwQHv8P
fL/ZGHBlf8s+uTeHfluG95bIe8VAGRwEwCyV5t+emBLq4ny5Q21MjWGDD3YjkKjA
lqC7c2mpCC6YVxBArVVm1G7/d8mpBuO5ZzyqIVkEhxZuYPfK6k7EEKx3BuCC97UT
ZcSVJBCHmxbxWm/U30VIpu0HDlbCiHX0OSDRJhv32ppazDonGSp/GiBocXNKTLA+
PyXQqRvObovTFPMutzLQDczeee5zvfJ7Gs7xCskcsLp8uBuhGJMnW87hRglm4p0/
tdIViIbMrwbVxjtHPnp5MARvQBT26ZzE3k0zr9Do3Gi6AY8Jt6ssD6r5CXbBA5SF
iGgp1czWb2xToqJtzuEjG1ssBj5MTMzINa4bMhQs52nXdUI2aG7n7mwoAVR3tHiW
sK1lvdsCAwEAAaNRME8wCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
VR0OBBYEFHrmiNrp+Fw+BwTeEaI4Iql1oxOrMBAGCSsGAQQBgjcVAQQDAgEAMA0G
CSqGSIb3DQEBBQUAA4ICAQCuLfQSOcRoQ8EcuVMgIVjepuonY1MG7PhPvJ1fyanw
0MeKonNZ4a7gOop7R/8DSGBfnQMQJClVcFTxe8Osa88OkeJmb9LQix9wMfR1GAaw
NwaX6ve0x4Ixr7m3KQEBOc+fAAGNLcxnlIDUD9EiSlFqqH+HkjxREU5RmE0TQFVS
NfNtwFSX0loMuL8mo10m8CD/ETRdq6jXO6vMWll8wBirSD9/Zostn5+t1g6TU4fi
bpR/56ueiRh0px2A1lhDTTGjV7UTqPvavUqJejZJCHf269xJb1r8mc+AJn/O4g4q
WvVsTILLMw+Oit/7ZagFbjZa7jSBRFfEyU4lKnV9oxIO47FTjWgGi7R+Rg8VDWvQ
a5JMhMadUWrz5VQRY9iBr1wlmvZH5100otrikZLfVxQ+HZVccgLvZ4BJpdk+Lzyk
bqZSAwbOJlFF0po+4wWbakhzS/jZLcoO8NzE4SgW3NTcuWYsS2G8ubV139IykSCy
RA9UcyoNNQM8CXr6I2UmhQwBqMrGZIi/rybPRQvlVSssuusfbxIiWMjdo/mQyUH2
A1diiIt1bpkVdJ9yRSDtuldoYe2w0QtId6WWAg2H8bTiF+/cu1kZ//rcK5UQyuku
1ggS22YqWCUrSQ4/heQdP1Ni619sMHFcMYWZTP5XySLiN+BBrs6/4pnJOVNsy742
KQ==
-----END CERTIFICATE-----

PS C:\&amp;gt; $cert &amp;gt; file.cer
PS C:\&amp;gt; &amp;amp; c:\file.cer
PS C:\&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Последней строчкой я вызвал команду, которая покажет мне сертификат как я бы запустил сам файл (я это и сделал этой командой на самом деле). Если там сертификат не один, то следующий сертификат можно было бы получить вот такой командой:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#0000ff"&gt;$CertAdmin.GetCAProperty(&amp;quot;ServerName\CA Name&amp;quot;, 0xC, 1, 3, 0)&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Я просто увеличил PropIndex на единицу. Чтобы узнать сколько же там всего сертификатов, достаточно посмотреть PropID = 0x0B, PropType = 1 (т.к. команда нам вернёт число, то тип должен быть числовой — &lt;strong&gt;Long&lt;/strong&gt;):&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;PS C:\&amp;gt; $CertAdmin.GetCAProperty(&amp;quot;ca\sysadmins-lv-ca&amp;quot;, 0xb, 0, 1, 0)
1
PS C:\&amp;gt;&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Вот в данном случае у меня там всего 1 сертификат. На другом сервере у меня 2 сертификата:&lt;/p&gt;

&lt;div style="width: 935px"&gt;
  &lt;blockquote&gt;
    &lt;pre style="background-color: #000040; font: 9pt consolas, lucida console"&gt;&lt;font color="#c0c0c0"&gt;&lt;span&gt;&lt;p&gt;[Administrator] $CertAdmin.GetCAProperty(&amp;quot;dc1\contoso ca&amp;quot;, 0xb, 0, 1, 0)
2
[Administrator]&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Если вам это интересно, то советую поупражняться в получении различных свойств в различном формате с использованием ICertAdmin2 интерфейса и таблички: &lt;a href="http://msdn.microsoft.com/en-us/library/cc249749(PROT.10).aspx" target="_blank"&gt;&lt;strong&gt;3.2.1.4.2.2 ICertRequestD2::GetCAProperty (Opnum 7)&lt;/strong&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Это была первая часть использования CryptoAPI в PowerShell. В следующих частях мы рассмотрим другие интересные методы интерфейса &lt;strong&gt;ICertAdmin2&lt;/strong&gt;.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=1cec0947-9113-4de2-bf48-809a09849f4c"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,1cec0947-9113-4de2-bf48-809a09849f4c.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / CryptoAPI</category>
    </item>
  </channel>
</rss>