<?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 | Certificates</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 | Certificates</title>
      <link>http://www.sysadmins.lv/</link>
    </image>
    <language>en-us</language>
    <copyright>Vadims Podāns</copyright>
    <lastBuildDate>Sun, 18 Apr 2010 09:46:11 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=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=2dc109a8-2a1a-4091-9a0d-eb28f4c87159</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,2dc109a8-2a1a-4091-9a0d-eb28f4c87159.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,2dc109a8-2a1a-4091-9a0d-eb28f4c87159.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=2dc109a8-2a1a-4091-9a0d-eb28f4c87159</wfw:commentRss>
      <title>Active Directory PKI object management с помощью PowerShell (часть 3)</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,2dc109a8-2a1a-4091-9a0d-eb28f4c87159.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,2dc109a8-2a1a-4091-9a0d-eb28f4c87159.aspx</link>
      <pubDate>Mon, 14 Dec 2009 18:47:12 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Продолжаем серию постов, которые посвящены базовому управлению объектами PKI в Active Directory. На данный момент мы рассмотрели сценарии публикации и просмотра сертификатов в Active Directory:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx"&gt;Active Directory PKI object management с помощью PowerShell&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,55c5304e-baef-4af6-bc0f-e09c214fb630.aspx"&gt;Active Directory PKI object management с помощью PowerShell (часть 2)&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;На данном этапе нам осталось последнее — удаление сертификатов из AD. Логика здесь очень простая: командой &lt;strong&gt;Get-ADPKIObject&lt;/strong&gt; мы получаем коллекцию объектов, которые представляют собой сертификаты и через конвейер командой &lt;strong&gt;Remove-ADPKIObject&lt;/strong&gt; указываем &lt;strong&gt;ID&lt;/strong&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;Remove-ADPKIObject&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
    Deletes certificates from Active Directory containers
.Description
    Deletes certificates from Active Directory containers by specifying particular ID or IDs
.Parameter ID
    Specifies certificate ID to delete that was set in Get-ADPKIObject command.
.EXAMPLE
    Get-ADPKIObject RootCA | Remove-ADPKIObject 2
    
    deletes certificate with ID = 2 in certificate viewer
.Outputs
    This command provide a resultant of operation.
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&amp;gt;&lt;/span&gt;&lt;span style="color: #000000"&gt;
    &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;int&lt;/span&gt;&lt;span style="color: #000000"&gt;[]]&lt;/span&gt;&lt;span style="color: #800080"&gt;$ID&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;throw&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;you must specify number of the object to delete&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; объявляем массив для хранения сертификатов из контейнера NTAuthCertificates&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;begin&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800080"&gt;$sum&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;process&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;if&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;.Container &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-ne&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;NTAuthCertificates&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; если это не NTAuthCertificates, то проверяем, что ID текущего объекта&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; совпадает с ID, который нужно удалить&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (@(&lt;/span&gt;&lt;span style="color: #800080"&gt;$ID&lt;/span&gt;&lt;span style="color: #000000"&gt;) &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-contains&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;.Id) {
                &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; если совпал, то собираем LDAP-запрос&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;$ldap&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;ADSI&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;LDAP://CN=$($_.Container),$script:ConfigContext&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; и удаляем текущий объект из AD&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;$retn&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.Delete(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;certificationAuthority&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;CN=$($_.Subject)&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;if&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;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;`'$($_.Subject)`' certificate was sucessfully deleted from `'$($_.Container)`' container&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&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; если контейнер текущего объекта является NTAuthCertificates, то собираем их все в массив&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;else&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #800080"&gt;$sum&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: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;}
    }
    &lt;/span&gt;&lt;span style="color: #0000ff"&gt;end&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; проверяем, что массив непустой (т.е. надо что-то удалять из NTAuthCertificates)&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$sum&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; т.е. ID которых не содержится в аргументах скрипта&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;$sum&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;$sum&lt;/span&gt;&lt;span style="color: #000000"&gt; |?{&lt;/span&gt;&lt;span style="color: #800080"&gt;$ID&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-notcontains&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;.Id})
            &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; делаем LDAP-запрос к этому контейнеру&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;$ldap&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;ADSI&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;LDAP://CN=$($_.Container),$script:ConfigContext&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; проверяем, что после фильтрации, хотя бы один сертификат нужно оставить&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$sum&lt;/span&gt;&lt;span style="color: #000000"&gt;.count &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-ge&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; записываем первый сертификат. Это необходимо потому что ADSI не поддерживает запись&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; массива сертификатов в свойство cACertificate, а только один сертификат в виде byte[]&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;cACertificate&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;byte&lt;/span&gt;&lt;span style="color: #000000"&gt;[]]&lt;/span&gt;&lt;span style="color: #800080"&gt;$sum&lt;/span&gt;&lt;span style="color: #000000"&gt;[0].RawCertificate)
                &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; а вот простое добавление он поддерживает. Тогда ADSI сам пересоберёт объекты&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: #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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; текущей строки. Но это не проблема, поскольку метод SetInfo() записывает только уникальные&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: #800080"&gt;$sum&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.cACertificate &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;byte&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;.RawCertificate)}
                &lt;/span&gt;&lt;span style="color: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.SetInfo()
                &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: #000080"&gt;$?&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;`'$($_.Subject)`' certificate was sucessfully deleted from `'$($_.Container)`' container&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; сертификаты из этого контейнера удаляются. Поэтому мы просто удаляем запись NTAuthCertificates.&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;else&lt;/span&gt;&lt;span style="color: #000000"&gt; {
                ([&lt;/span&gt;&lt;span style="color: #008080"&gt;ADSI&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;LDAP://$script:ConfigContext&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;).Delete(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;certificationAuthority&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;CN=NTAuthCertificates&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;if&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;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;All certificates was sucessfully deleted from NTAuthCertificates entry .&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&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;This was last certificate in contaner. NTAuthCertificates entry is removed from Active Directory&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;И теперь можно подвести краткие итоги. Мы смогли реализовать функционал certutil и других графических утилит (консоли MMC) в PowerShell значительно улучшив читабельность выходных объектов, адаптировали под работу из консоли (синтаксис стал значимо короче и более юзерфрендли) и шаг за шагом делаем из PowerShell единое консольное средство управления различными аспектами PKI.&lt;/p&gt;

&lt;p&gt;Можно задать вопрос: а кто целевая аудитория всего этого? Целевая аудитория есть — администраторы PKI. Просто у вас не всегда будет возможность использовать графические консоли для решения этих задач (потому что их функционал далёк от идеального). Можно использовать certutil, который умеет много чего, но тоже имеет свои недостатки. Это и ужасный синтаксис, и вырвиглазный неуправляемый вывод результатов. Вобщем я надеюсь, что рано или поздно PowerShell сможет по-настоящему заменить certutil (который вообще-то ни в чём не виноват) и стать единой консолью всех Windows-администраторов. Вот не знаю на сколько это хорошо или плохо, потому что Microsoft всех насильно переводит на PowerShell (это очень показательно продемонстрировано в MS Exchange, где у вас по сути есть только PowerShell и всё). Обычно, насильно переводят на другой инструмент когда он является УГ и очень тяжело на него перевести людей посредством обычной рекламы. Но является ли PowerShell таким УГ? Я пока не готов ответить на этот вопрос. Моё мнение — PowerShell пока что особой революцией не стал. Даже не смотря на тонны рекламы, пеара и прочего, где восхваляют PowerShell, закидывают ногами CMD/WSH. Это обусловлено тем фактом, что не всегда PowerShell бывает удобней CMD/WSH, особенно в тривиальных задачах. Говорить, что синтаксис стал более простым и компактным тоже нельзя, потому что реально функционала из коробки хватает для решения процентов 10 задач. Всё остальное нужно скриптовать и программировать (да-да!) самому. Благо средств для этого в PowerShell хватает. Во что это обычно выливается? А в то, что в большинстве случаев результирующий объём кода будет не сильно меньше, чем в связке WSH + CMD. В любом случае преимущества PowerShell перед остальными очевидны, но они далеко не определяющие, ведь люди раньше решали свои задачи на WSH/CMD, пирожки продавались, бизнес шёл. С одной стороны Microsoft дал людям простор для творчества, т.е. делать в PowerShell всякие потрясающие штуки и всё такое. Но это не совсем то, что нужно было администраторам. Им нужна одна кнопка на весь экран с надписью «Сделать всё п**дато!». Пока что PowerShell и близко не готов стать такой кнопкой, а является «удочкой». Т.е. удочка у вас уже есть, а что касается конечной рыбы (результата), то дело осталось за малым — написать мега-скрипт. Мне вот интересно, что думают администраторы Exchange (поскольку пока что только они получили полноценную поддержку для своего продукта в PowerShell) — стало ли им жить легче с PowerShell или нет? Если да, то это может быть хорошим знаком, что однажды PowerShell станет такой кнопкой. И не будет более в системе certutil и всеми задачами будет рулить PowerShell (пока что это наиболее логичный сценарий развития событий). А вот если их жизнь не стала легче, то обещанной революции (которая по словам Microsoft уже наступила, как и вендекапец у луноходов) не будет, а будет просто какое-то логическое продолжение предыдущих инструментов для сценариев.&lt;/p&gt;

&lt;p&gt;К чему я написал столько букв? К тому, что я ежедневно задаю себе один и тот же вопрос: а зачем я всё это делаю? А ответ найти очень непросто, потому что отмазы вида «проще, удобней, красивее» не годятся для серьёзного аргумента. На самом деле я не ищу ответ на него, а просто говорю себе «так надо» и делаю. Поэтому не надо меня использовать как пример «правильного пользователя PowerShell» и пытаться повторить что-то подобное астрономических масштабов на овер9000 строк — поверьте, оно не стоит того. Используйте его по мере сил. Если чего-то будет не хватать и его решение потребует значительных усилий — посмотрите на готовые утилиты, они наверняка будут уметь то, что вам надо.&lt;/p&gt;

&lt;p&gt;Удачи!© One&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=2dc109a8-2a1a-4091-9a0d-eb28f4c87159"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,2dc109a8-2a1a-4091-9a0d-eb28f4c87159.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / Certificates</category>
      <category>PowerShell / Certificates / Active Directory</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=55c5304e-baef-4af6-bc0f-e09c214fb630</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,55c5304e-baef-4af6-bc0f-e09c214fb630.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,55c5304e-baef-4af6-bc0f-e09c214fb630.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=55c5304e-baef-4af6-bc0f-e09c214fb630</wfw:commentRss>
      <title>Active Directory PKI object management с помощью PowerShell (часть 2)</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,55c5304e-baef-4af6-bc0f-e09c214fb630.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,55c5304e-baef-4af6-bc0f-e09c214fb630.aspx</link>
      <pubDate>Fri, 11 Dec 2009 21:09:45 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;В &lt;a href="http://www.sysadmins.lv/PermaLink,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx"&gt;&lt;strong&gt;предыдущем посте&lt;/strong&gt;&lt;/a&gt; мы ознакомились с основными контейнерами с объектами PKI в Active Directory и смогли изучить функциональный аналог ключа dspublish в утилите certutil. Если публикация сертификатов в AD задача простая даже для Certutil, то просмотр содержимого может быть весьма нетривиальным. Например, если вы хотите посмотреть содержимое записи NTAuthCertificates, то придётся выполнить вот такую команду:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font color="#0000ff"&gt;certutil –viewstore &amp;quot;CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration, ForestRootDomainDN&amp;quot;&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;такие вещи совершенно неприспособлены к командной строке, поскольку надо набирать много текста и ошибиться весьма просто. Одно хорошо, команда выводит графическое окошко, где мы можем посмотреть содержимое. Но тут есть несколько неудобных моментов: мы не можем посмотреть несколько контейнеров сразу, для каждого контейнера надо выполнять отдельную команду. В этом окошке мы можем только посмотреть на содержимое контейнера и всё. Ни добавить, ни удалить сертификат мы не можем. Для добавления сертификатов мы можем воспользоваться тем же certutil или моим скриптом, который был опубликован в предыдущем посте. Графика — хорошо и замечательно, но мы можем хотеть автоматизировать какие-то задачи или просто посмотреть информацию в консоли. Вы можете подумать, что это не нужно, но преимущество между консольным выводом и графическим диалоговым окном очевидное: из первого можно копировать информацию в буфер обмена. Есть ещё вариант — для просмотра и удаления сертификатов из AD, пользоваться консолью pkiview.msc. Но мы сразу же теряем главную нить — единое средство управления. Т.е. даже похожие операции мы должны выполнять в разных инструментах! Но с появлением PowerShell мы получили единый (хоть и консольный) инструмент, которым можно автоматизировать абсолютно всё! Даже сам PowerShell &lt;img alt=":)" src="/smilies/happy.gif"&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;Get-ADPKIObject&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
    Displays certificates info from Active Directory containers
.Description
    Displays info about certificates that are stored in AD PKI-related containers.
.Parameter Container
    Optional parameter. Specifies particular container to view. May contain one or
    more value from following possible values:
    
    RootCA - retrieves certificates from Certification Authorities container
    SubCA - retrieves certificates from AIA container
    NTAuthCA - retrieves certificates from NTAuthCertificate directory entry.
    
    if no parameter is set, command will return all certificates from all applicable
    containers.
.EXAMPLE
    Get-ADPKIObject RootCA
    
    Retrieves certificates from Certification Authorities container
.EXAMPLE
    Get-ADPKIObject RootCA, AIA
    
    Retrieves certificates from Certification Authorities and AIA containers
.Outputs
    Output AD PKI object collection
&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;[]][ValidateSet(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;RootCA&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;SubCA&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;NTAuthCA&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;&amp;quot;&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: #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: #800080"&gt;$script:sum&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; это весьма крутая штука будет. Каждый объект будет содержать свойство Id или просто&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; будет указать его Id вместо длинных и неудобных LDAP/Thumpbrint значений, как это делается&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; в certutil и подобных ему утилитах. Нумерацию начнём с единицы&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;$script: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;1&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;function&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;_formatter_&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$type&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$name&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; поскольку у нас все объекты в AD находятся в бинарном формате, мы импортируем каждый из них&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; в X509Certificate2 объект.&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;$certs&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Import(&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: #800080"&gt;$current&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;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt; | &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;select&lt;/span&gt;&lt;span style="color: #000000"&gt; @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;Id&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$script:n&lt;/span&gt;&lt;span style="color: #000000"&gt;}}, Subject, @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;Type&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$type&lt;/span&gt;&lt;span style="color: #000000"&gt;}}, @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;Container&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$name&lt;/span&gt;&lt;span style="color: #000000"&gt;}},
                @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;Thumbprint&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Thumbprint}}, @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;SerialNumber&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.SerialNumber}}, 
                @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;ValidFrom&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotBefore}}, @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;ValidTo&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.NotAfter}}, 
                @{n&lt;/span&gt;&lt;span style="color: #ff0000"&gt;=&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;RawCertificate&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;;e&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.RawData}}
            &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; чтобы не писать полный DN поля Subject, мы будем показывать только первую его часть&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-match&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;CN=([^,]+)&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;)
            &lt;/span&gt;&lt;span style="color: #800080"&gt;$current&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;$matches&lt;/span&gt;&lt;span style="color: #000000"&gt;[1]
            &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: #800080"&gt;$script:sum&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;$current&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; очищаем X509Certificate2&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Reset()
            &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: #800080"&gt;$script:n&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; ещё одна суб-функция, которая выдёргивает сертификаты из AD в бинарном виде и отправляет&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; их в _formatter_, который уже сформирует итоговые объекты.&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;_switcher_&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$name&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: #800080"&gt;$ldap&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;ADSI&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;LDAP://CN=$name,$script:ConfigContext&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; как мы знаем, NTAuthCertificates не является контейнером, поэтому для него код будет немного&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; свойства объекта NTAuthCA&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$name&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-eq&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;NTAuthCertificates&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; убеждаемся, что длина первого элемента свойства cACertificate больше единицы, т.е. содержит ненулевое&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; значение. Так же проверяем свойство crossCertificatePair, которое содержит Cross-certificates&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: #0000ff"&gt;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.cACertificate[0].count &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-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: #800080"&gt;$certs&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.cACertificate)
                &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;_formatter_&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&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;CA Certificate&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;$name&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.crossCertificatePair[0].count &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-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: #800080"&gt;$certs&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.cACertificate)
                &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;_formatter_&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&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;Cross CA Certificate&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;$name&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;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; если контейнер указан как Certification Authority и/или AIA, то заглядываем&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: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.psbase.children | &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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; и заглядываем в каждую запись на исследование свойств cACetificate и crossCertificatePair&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;$certs&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: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;.cACertificate)
            &lt;/span&gt;&lt;span style="color: #800080"&gt;$ccerts&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: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;.crossCertificatePair)
            &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: #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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&lt;/span&gt;&lt;span style="color: #000000"&gt;[0].count &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-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: #5f9ea0"&gt;_formatter_&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&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;CA Certificate&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;$name&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;$ccerts&lt;/span&gt;&lt;span style="color: #000000"&gt;[0].count &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-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: #5f9ea0"&gt;_formatter_&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$ccerts&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;Cross CA Certificate&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;$name&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;$Container&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; конструкцией switch проверяем содержимое аргумента функции, чтобы определить какие именно&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: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;RootCA&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: #5f9ea0"&gt;_switcher_&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;Certification Authorities&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;SubCA&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: #5f9ea0"&gt;_switcher_&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;AIA&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;NTAuthCA&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: #5f9ea0"&gt;_switcher_&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;NTAuthCertificates&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; если контейнер в аргументе не указан, то проверяем все контейнеры и записи&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: #800000"&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt; {
            &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;_switcher_&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;Certification Authorities&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: #5f9ea0"&gt;_switcher_&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;AIA&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: #5f9ea0"&gt;_switcher_&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;NTAUthCertificates&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; когда вывод будет полностью сформирован, выбрасываем все объекты в консоль&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;$script:sum&lt;/span&gt;&lt;span style="color: #000000"&gt;
}&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; данная функция является частью файла &lt;strong&gt;dspublish.ps1&lt;/strong&gt;, т.к. использует глобально объявленные переменные.&lt;/p&gt;

&lt;p&gt;и вывод у него вот такой красивый: 
  &lt;br /&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;Id             : 3
Subject        : Contoso CA
Type           : CA Certificate
Container      : AIA
Thumbprint     : BA8FECE99165E68CE27C9F0AF5F0664FDA39F7A2
SerialNumber   : 5DD87E4CFFE3B3BC43F608EB57C767F7
ValidFrom      : 2009.02.15. 16:31:15
ValidTo        : 2014.02.15. 16:40:11
RawCertificate : {48, 130, 4, 98...}

Id             : 4
Subject        : sysadmins-LV-CA
Type           : Cross CA Certificate
Container      : AIA
Thumbprint     : 1A28B582E21803D2BFE0DAEEF4593DE372C8EC3C
SerialNumber   : 170AD11B0000000000A7
ValidFrom      : 2009.11.24. 19:43:10
ValidTo        : 2011.03.30. 17:06:53
RawCertificate : {48, 130, 7, 94...}&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;pre&gt;&lt;span style="color: #0000ff"&gt;filter&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;View-ADPKIObject&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
    Displays certificates in certificate viewer
.Description
    Displays certificates in certificate viewer by selecting necessary certificates ID.
    Must be placed after Get-ADPKIObject command only.
.Parameter ID
    Specifies certificate ID that was set in Get-ADPKIObject command.
.EXAMPLE
    Get-ADPKIObject RootCA | ViewADPKIObject 1, 3
    
    displays certificate with ID = 2 in certificate viewer
.Outputs
    Script doesn't generate any output except errors
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&amp;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; судя по конструкции int[] мы можем указать несколько чисел, тогда все выбранные&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: #0000ff"&gt;param&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;$ID&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;throw&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;you must specify number of the object to display&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; и проверяем входные объекты с конвейера на предмет их ID. Если ID совпадает с&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; одним из ID в аргументах, обрабатываем его. Если ID не совпадает, ничего не делаем.&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (@(&lt;/span&gt;&lt;span style="color: #800080"&gt;$ID&lt;/span&gt;&lt;span style="color: #000000"&gt;) &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-contains&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;.Id) {
        &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; генерируем в пользовательской папке Temp временный файл с рандомным расширением&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;$TempFile&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.IO.Path&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;GetTempFileName&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;.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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; записываем бинарный массив сертификата в файл в виде DER кодировки&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;System.IO.File&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;WriteAllBytes&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800080"&gt;$TempFile&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;.RawCertificate)
        &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;        &amp;amp; &lt;/span&gt;&lt;span style="color: #800080"&gt;$TempFile&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: #5f9ea0; font-weight: bold"&gt;Start-Sleep&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;0.5&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: #5f9ea0; font-weight: bold"&gt;del&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$TempFile&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Force&lt;/span&gt;&lt;span style="color: #000000"&gt;
    }
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Как вы видите, ничего сверх-космического или магического в этом коде нет, самое трудное здесь — придумать логику работы. А остальное — накидать несколько строк кода и у нас PowerShell в лёгкую может соперничать с certutil за право называться единой утилитой управления PKI &lt;img alt=":)" src="/smilies/happy.gif"&gt;&lt;/p&gt;

&lt;p&gt;Чтобы подкрутить рейтинг PowerShell в этой конкуренции, в следующий раз я покажу как мы можем легко и просто удалять сертификаты из контейнеров AD с использованием PowerShell &lt;img alt=":)" src="/smilies/happy.gif"&gt;&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=55c5304e-baef-4af6-bc0f-e09c214fb630"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,55c5304e-baef-4af6-bc0f-e09c214fb630.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / Certificates</category>
      <category>PowerShell / Certificates / Active Directory</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=dd03c789-780d-4b39-9b7b-310905ecde32</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=dd03c789-780d-4b39-9b7b-310905ecde32</wfw:commentRss>
      <title>Active Directory PKI object management с помощью PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx</link>
      <pubDate>Wed, 09 Dec 2009 19:35:17 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Подоспела ещё одна задачка для PowerShell'а — управление объектами PKI в Active Directory. Active Directory содержит целый раздел посвящённый PKI и вот из чего он состоит:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font color="#0000ff"&gt;CN=NTAuthCertificates, CN=Public Key Services, CN=Services, CN=Configuration, &lt;em&gt;ForestRootDomain&lt;/em&gt;&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;CN={CA name},CN=AIA, CN=Public Key Services, CN=Services, CN=Configuration, &lt;em&gt;ForestRootDomain&lt;/em&gt;&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;CN={CA name},CN=CDP, CN=Public Key Services, CN=Services, CN=Configuration, &lt;em&gt;ForestRootDomain&lt;/em&gt;&lt;/font&gt; &lt;/li&gt;    &lt;li&gt;&lt;font color="#0000ff"&gt;CN={CA name},CN=Certification Authority, CN=Public Key Services, CN=Services, CN=Configuration, &lt;em&gt;ForestRootDomain&lt;/em&gt;&lt;/font&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Вот о них мы сегодня и поговорим. В AD есть ещё несколько контейнеров, которые связаны с PKI, но они сегодня интереса представлять не будут. Как мы уже знаем, в:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;NTAuthCertificates&lt;/strong&gt; публикуются все сертификаты CA, которые выдают сертификаты для аутентификации пользователей в домене. В том числе для логона смарт-картой, аутентификации в IIS или для аутентификации EAP-TLS в VPN. Все сертификаты в этой записи хранятся в виде массива; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;AIA&lt;/strong&gt; публикуются сертификаты промежуточных (Intermediate) CA, за счёт чего можно значительно сократить время построения цепочек сертификатов. При этом не обязательно должен содержать сертификаты CA, которые зарегистрированы в текущем лесу. Это могут быть сертификаты промежуточных CA сторонних компаний, сертификаты которых вы используете. По большому счёту сюда должны публиковаться все сертификаты; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;CDP&lt;/strong&gt; публикуются CRL списки CA для ускорения проверки сертификатов в цепочке. Так же, как и в случае с AIA не обязательно может содержать CRL'ы CA только текущего леса. Сюда могут публиковаться и CRL сторонних CA, сертификаты которых вы используете; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Certification Authority&lt;/strong&gt; публикуются сертификаты корневых CA, которым должен доверять весь лес. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Вы спросите, а зачем это всё, если то же самое можно сделать через групповые политики? Ответ тут достаточно очевиден. Дело в том, что PKI не видит границ доменов и эти сертификаты распространяются по всему лесу вместе с репликацией. Поэтому для добавления нового доверенного корневого CA вам придётся создавать одинаковую политику в каждом домене леса. И вы некоторые объекты (например CRL) не можете распространять через GPO.&lt;/p&gt;  &lt;p&gt;Какие у нас есть инструменты для управления данными контейнерами? Их у нас несколько:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;ADSIEdit.msc&lt;/strong&gt; — обеспечивает только просмотр содержимого контейнеров в AD (но сами записи там нечитабельны); &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;PKIView.msc&lt;/strong&gt; — позволяет просматривать содержимое каждого контейнера и удалять оттуда сертификаты. C использованием данной консоли мы можем добавлять сертификаты только в NTAuthCertificates. Остальные — только чтение и удаление; &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;certutil&lt;/strong&gt; — интерфейс командной строки, который позволяет добавлять, просматривать контейнеры и удалять сертифакты из них. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Кажется, что certutil'а хватит всем. Но у него есть одна большая проблема — ужасный синтаксис. Напрмер, если вы хотите посмотреть CRL'ы в AD, то придётся делать что типа такого:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p align="left"&gt;&lt;font color="#0000ff"&gt;certutil –viewstore ldap:///CN=MyCA,CN=CRL,CN=CDP,CN=Public%20Key%        &lt;br /&gt;20Services,CN=Services,CN=Configuration,DC=contoso,DC=com?certificateRevocationList?base?objectClass=cRLDistributionPoint&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;этот синтаксис возможно чем-то универсален, но cовершенно неудобный для использования в командной строке, поэтому я поставил задачу решить этот вопрос с помощью PowerShell. И вот как я его решил:&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; к сожалению я не в состоянии объяснять все особенности работы ADSI и PowerShell, поэтому для понимания работы скрипта нужно иметь представление и некоторый опыт скриптования с использованием ADSI и PowerShell.&lt;/p&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; dspublish.ps1&lt;/span&gt;&lt;span style="color: #008000"&gt;
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Version 0.7&lt;/span&gt;&lt;span style="color: #008000"&gt;
#
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Adds certificates in Active Directory containers&lt;/span&gt;&lt;span style="color: #008000"&gt;
#
#&lt;/span&gt;&lt;span style="color: #008000"&gt; Vadims Podans (c) 2009&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: #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; скрипта, чтобы предотвратить фатальные изменения в Active Directory&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #0000ff"&gt;trap&lt;/span&gt;&lt;span style="color: #000000"&gt; {&lt;/span&gt;&lt;span style="color: #0000ff"&gt;break&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;$script:ConfigContext&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.DirectoryServices.ActiveDirectory.Domain&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;GetCurrentDomain&lt;/span&gt;&lt;span style="color: #000000"&gt;().&lt;/span&gt;&lt;span style="color: #8b4513"&gt;GetDirectoryEntry&lt;/span&gt;&lt;span style="color: #000000"&gt;().distinguishedName
&lt;/span&gt;&lt;span style="color: #800080"&gt;$script:ConfigContext&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=Public Key Services,CN=Services,CN=Configuration,&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;+&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$script:ConfigContext&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$script: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: #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;Publish-ADPKIObject&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
    Publishes certificates to Active Directory containers
.Description
    Publishes certificates to Public Key Services containers in Active Directory.
.Parameter File
    Specifies the path to certificate file or X509Certificate2 object.
    Certificates may be passed through pipeline.
.Parameter Container
    Specifies the AD PKI container to publish file. For certificates only
    following containers MUST be used:
    
    RootCA - indicates that certificate will be published to Certification Authorities container
    SubCA - indicates that certificate will be published to AIA container
    NTAuthCA - indicates that certificate will be added to NTAuthCertificate directory
    entry. If not exist, entry will be created.
    
    you MAY specify several containers at once. Certificate will be added to all
    specified containers. Entry names are based on certificate subject.
    
.Parameter Force
    forces object rewrite if object already exist in Active Directory
.EXAMPLE
    dir *.cer | Publish-ADPKIObject RootCA, SubCA
    
    will publish all .CER certificates to Certification Authorities and AIA containers
.EXAMPLE
    Publish-ADPKIObject certificate.cer RootCA -Force
    
    will publish 'Certificte.cer' certificate to Certification Authorities container. If
    object already exist, it will rewrited
.Outputs
    This command provide a resultant of operation.
&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;(
        [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: #800080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;, ValueFromPipeline &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;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;, Position &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: #008080"&gt;object&lt;/span&gt;&lt;span style="color: #000000"&gt;[]]&lt;/span&gt;&lt;span style="color: #800080"&gt;$file&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: #800080"&gt;$true&lt;/span&gt;&lt;span style="color: #000000"&gt;, Position &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: #008080"&gt;string&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: #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: #0000ff"&gt;begin&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; функция, которая будет осуществлять запись сертификатов в AD&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;_ldaproutine_&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$CN&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$name&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;$path&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;ADSI&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;LDAP://$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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; убеждаемся, что такой же объект не существует в AD&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; ($(&lt;/span&gt;&lt;span style="color: #800080"&gt;$path&lt;/span&gt;&lt;span style="color: #000000"&gt;.psbase.children | ?{&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;.cn &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-eq&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$CN&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; если существует, проверяем ключ Force, который позволяет перезаписывать&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: #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: #800080"&gt;$ldap&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;ADSI&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;LDAP://CN=$CN,$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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; если ключ Force указан, то мы просто перезаписываем свойство&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; cACertificate новым сертификатом&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;cACertificate&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.RawData)
                    &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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; надо записать в AD методом SetInfo()&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;$retn&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.SetInfo()
                    &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: #000080"&gt;$?&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;`'$CN`' certificate is sucessfully rewrited to `'$name`' container&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&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; если объект уже существует и ключ Force не указан, то просто выводим сообщение, что такой объект уже существует&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;else&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;Object already exist in `'$name`' container. Use -Force switch to rewrite&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;else&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; с типом certificationAuthority&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;$CA&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;$path&lt;/span&gt;&lt;span style="color: #000000"&gt;.Create(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;certificationAuthority&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;CN=$CN&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; записываем сертификат в свойство cACertificate в бинарном виде из объекта X509Certificate2&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;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.Put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;cACertificate&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.RawData)
                &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: #800080"&gt;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.Put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;authorityRevocationList&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: #800080"&gt;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.Put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;certificateRevocationList&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; когда объект сформирован, записываем его в AD&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;$retn&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;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.SetInfo()
                &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: #000080"&gt;$?&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;`'$CN`' certificate is sucessfully added to `'$name`' container&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&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: #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;process&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: #800080"&gt;$script:Certificate&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;gi&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$file&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-ErrorAction&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Stop&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; проверяем, что объект не является готовым объектом X509Certificate2&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;if&lt;/span&gt;&lt;span style="color: #000000"&gt; (&lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-isnot&lt;/span&gt;&lt;span style="color: #000000"&gt; [&lt;/span&gt;&lt;span style="color: #008080"&gt;System.Security.Cryptography.X509Certificates.X509Certificate2&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; допускаются только расширения CER и CRT&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;if&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;.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: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;.crt&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;-contains&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt;.Extension) {
                &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; если это CER или CRT файл, то конвертируем его в объект X509Certificate2&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Import(&lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt;.FullName)
                &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; в переменную $CN записываем первую часть поля Subject сертификата&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-match&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;CN=([^,]+)&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;)
                &lt;/span&gt;&lt;span style="color: #800080"&gt;$CN&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;$matches&lt;/span&gt;&lt;span style="color: #000000"&gt;[1]
            }
        &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; если у нас на конвейер или через аргументы поступил готовый X509Certificate2, то только выбираем&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; поле Subject в отдельную переменную.&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;else&lt;/span&gt;&lt;span style="color: #000000"&gt; {
            &lt;/span&gt;&lt;span style="color: #800080"&gt;$script: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: #800080"&gt;$script:Certificate&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Subject &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-match&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;CN=([^,]+)&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt;)
            &lt;/span&gt;&lt;span style="color: #800080"&gt;$CN&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;$matches&lt;/span&gt;&lt;span style="color: #000000"&gt;[1]
        }
        &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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; я не делал проверку этих контейнеров в секции param() через использование ValidateSet&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; поскольку данная функция в будущем будет использоваться и для публикации CRL. А для&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; них нужно вручную прописывать имя записи в контейнере CDP и оно может быть произвольным.&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: #800080"&gt;$Container&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;$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;RootCA&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;SubCA&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;NTAuthCA&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;-contains&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;if&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: #800080"&gt;$Container&lt;/span&gt;&lt;span style="color: #000000"&gt;) {&lt;/span&gt;&lt;span style="color: #0000ff"&gt;throw&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;For certificate containers only following values are applicable: RootCA, SubCA, NTAuthCA&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; проверяем, что входной сертификат содержит свойство CertificateAuthority равным True.&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; это свойство соответствует расширению Basic Constraints в сертификате, которое может иметь&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; значения: Subject Type=CA - это сертификат CA и Subject Type=End entity, если это конечный&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; сертификат. А в X509Certificate2 конечный сертификат будет иметь значение False в свойстве&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; CertificateAuthority. Но работу скрипта не прерываем, а просто пропускаем текущий сертификат.&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;if&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: #800080"&gt;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Extensions | ?{&lt;/span&gt;&lt;span style="color: #000080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;.CertificateAuthority &lt;/span&gt;&lt;span style="color: #ff0000"&gt;-eq&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$true&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;Input certificate `'$CN`' is not recognized as CA certificate. Skipping&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; а теперь подготавливаем необходимые данные для записи в зависимости от названия контейнера&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;switch&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;RootCA&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; указываем название данного контейнера в AD&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;$name&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;Certification Authorities&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; получаем LDAP объект этого контейнера&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;$ldap&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=$name,$script:ConfigContext&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; и отправляем всё это в функцию записи&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: #5f9ea0"&gt;_ldaproutine_&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$CN&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$name&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Reset()
            }
            &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;SubCA&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; здесь то же самое, что и для RootCA&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;$name&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;AIA&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;$ldap&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=$name,$script:ConfigContext&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: #5f9ea0"&gt;_ldaproutine_&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$CN&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$name&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Reset()
            }
            &lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;NTAuthCA&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;$name&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;NTAuthCertificates&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;$ldap&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;ADSI&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;LDAP://CN=$name,$script:ConfigContext&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; поскольку NTAuthCertificates не является контейнером, а отдельной&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; здесь немного иные. Сначала проверяем, что эта запись уже существует в AD.&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;if&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: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.cn) {
                    &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: #800080"&gt;$CA&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;ADSI&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;LDAP://$script:ConfigContext&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #000000"&gt;).Create(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;certificationAuthority&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;CN=$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: #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: #800080"&gt;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.Put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;authorityRevocationList&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: #800080"&gt;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.Put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;certificateRevocationList&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: #800080"&gt;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.put(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;cACertificate&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;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.RawData)
                    &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; когда объект уже готов, то просто записываем его в AD&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;$retn&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;$CA&lt;/span&gt;&lt;span style="color: #000000"&gt;.SetInfo()
                    &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: #000080"&gt;$?&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;`'$CN`' certificate is sucessfully added to `'$name`' container&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&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; а вот если эта запись уже есть, то ничего создавать не надо, а просто добавляем&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; как массив (используется запятуя сразу за оператором). Это связано с особенностью работы PowerShell с&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: #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: #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: #800080"&gt;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.cACertificate &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;.RawData
                &lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; и записываем объект обратно в AD.&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;$retn&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;$ldap&lt;/span&gt;&lt;span style="color: #000000"&gt;.SetInfo()
                &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: #000080"&gt;$?&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;`'$CN`' certificate is sucessfully added to `'$name`' container&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="font-style: italic; color: #5f9ea0"&gt;-ForegroundColor&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;Green&lt;/span&gt;&lt;span style="color: #000000"&gt;}
                &lt;/span&gt;&lt;span style="color: #800080"&gt;$script:Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;.Reset()
            }
        }
    }
}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

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

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#0000ff"&gt;Publish-ADPKIObject &amp;lt;certificate&amp;gt; &amp;lt;container&amp;gt; –Force
      &lt;br /&gt;&amp;lt;certificate&amp;gt; | Publish-ADPKIObject –Force&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Причём вы можете указывать несколько контейнеров сразу, например: &lt;font color="#0000ff"&gt;Publish-ADPKIObject file.cer NTAuthCA, RootCA, SubCA&lt;/font&gt;. Я думаю, что этот скрипт получился не такой уж и сложный и его разобрать с помощью моих комментариев не так и сложно. Его можно спокойно расширить под другие контейнеры, например, CDP или KRA. Единственное, что здесь пока не реализовано — санитизация имён объектов. На сколько я знаю, certutil этого тоже не поддерживает. Но сделать её надо. Правда, я пока не нашёл ни одного стандартного механизма, который бы санитизировал имена &lt;img alt=":'(" src="/smilies/unhappy.gif"&gt;&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=dd03c789-780d-4b39-9b7b-310905ecde32"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,dd03c789-780d-4b39-9b7b-310905ecde32.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificate Authority</category>
      <category>PowerShell / Certificates</category>
      <category>PowerShell / Certificates / Active Directory</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=16ffa3d3-8449-4c16-9704-5d089b6a32e2</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,16ffa3d3-8449-4c16-9704-5d089b6a32e2.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,16ffa3d3-8449-4c16-9704-5d089b6a32e2.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=16ffa3d3-8449-4c16-9704-5d089b6a32e2</wfw:commentRss>
      <slash:comments>5</slash:comments>
      <title>Certificate chaining engine в PowerShell (часть 2)</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,16ffa3d3-8449-4c16-9704-5d089b6a32e2.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,16ffa3d3-8449-4c16-9704-5d089b6a32e2.aspx</link>
      <pubDate>Mon, 19 Oct 2009 18:52:44 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; данный материал публикуется на правах ТЗ (&lt;strong&gt;ТЗ&lt;/strong&gt; — &lt;em&gt;Тайное Знание&lt;/em&gt;) и обязателен для знания администраторам PKI.&lt;/p&gt;  &lt;p&gt;В предыдущей части (&lt;a href="http://www.sysadmins.lv/PermaLink,guid,b14ea574-ca90-4f1b-9845-35b6ce273fb2.aspx"&gt;&lt;strong&gt;Certificate chaining engine в PowerShell&lt;/strong&gt;&lt;/a&gt;) мы рассмотрели реализацию certificate chaining engine в .NET в виде класса &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx"&gt;&lt;strong&gt;X509Chain&lt;/strong&gt;&lt;/a&gt;&lt;strong&gt;&lt;/strong&gt;. Но этот рассказ был бы неполным, если мы не поговорили про &lt;a href="http://msdn.microsoft.com/en-us/library/aa377611(VS.85).aspx"&gt;&lt;strong&gt;CAPICOM.Chain&lt;/strong&gt;&lt;/a&gt;. Хоть Microsoft рекомендует использовать .NET, а не CAPICOM для решения данной задачи, я считаю необходимым осветить этот вопрос. Для начала начнём с реализации CAPICOM в PowerShell. По непонятным мне пока причинам мне не удалось завести его в PowerShell на системах Windows Vista и выше, поэтому примеры буду приводить на Windows Server 2003.&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 G:\&gt; $chain = New-Object -ComObject "CAPICOM.Chain"
PS G:\&gt; $chain

Certificates
------------



PS G:\&gt; $chain | gm -MemberType methods


   TypeName: System.__ComObject#{ca65d842-2110-4073-aee3-d0aa5f56c421}

Name                MemberType Definition
----                ---------- ----------
ApplicationPolicies Method     IOIDs ApplicationPolicies ()
Build               Method     bool Build (ICertificate)
CertificatePolicies Method     IOIDs CertificatePolicies ()
ExtendedErrorInfo   Method     string ExtendedErrorInfo (int)


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

&lt;p&gt;Так же, как и в .NET у нас есть метод &lt;a href="http://msdn.microsoft.com/en-us/library/aa377617(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;Build()&lt;/strong&gt;&lt;/a&gt;, который запускает certificate chaining engine для указанного сертификата. Но это COM объект и X509Certificate2 объекты не принимает. Поэтому мы средствами этого же CAPICOM получим нужный объект сертификата:&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 G:\&gt; $store = New-Object -ComObject "CAPICOM.Store"
PS G:\&gt; $store.Open(2,"my",128)
PS G:\&gt; $cert = @()
PS G:\&gt; $store.Certificates | %{$cert += $_}
PS G:\&gt; $cert = $cert[1]
PS G:\&gt; $cert


Version       : 3
SerialNumber  : 167D6D32000000000011
SubjectName   : CN=Administrator, CN=Users, DC=sysadmins, DC=lv
IssuerName    : CN=sysadmins-LV-CA, DC=sysadmins, DC=lv
ValidFromDate : 2009.08.07. 16:09:56
ValidToDate   : 2010.08.07. 16:09:56
Thumbprint    : 1FA71B51BCE461BEE24B11AA9EF855ED00DFDFD4
Archived      : False
PrivateKey    :



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

&lt;p&gt;Вот такой объект сертификата мы получили. Вот его и пропустим через метод Build():&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 G:\&gt; $chain.Build($cert)
False
PS G:\&gt; $chain.Status()
32
PS G:\&gt; $chain.Certificates


Version       : 3
SerialNumber  : 167D6D32000000000011
SubjectName   : CN=Administrator, CN=Users, DC=sysadmins, DC=lv
IssuerName    : CN=sysadmins-LV-CA, DC=sysadmins, DC=lv
ValidFromDate : 2009.08.07. 16:09:56
ValidToDate   : 2010.08.07. 16:09:56
Thumbprint    : 1FA71B51BCE461BEE24B11AA9EF855ED00DFDFD4
Archived      : False
PrivateKey    :

Version       : 3
SerialNumber  : 3DFFAF914D613282427BD591C1FB586D
SubjectName   : CN=sysadmins-LV-CA, DC=sysadmins, DC=lv
IssuerName    : CN=sysadmins-LV-CA, DC=sysadmins, DC=lv
ValidFromDate : 2009.08.06. 10:21:01
ValidToDate   : 2014.08.06. 10:30:54
Thumbprint    : E82ACC45841280DDEAB9F7847418FA26354457A7
Archived      : False
PrivateKey    :



PS G:\&gt; $chain.ApplicationPolicies()

                                   Name FriendlyName                            Value
                                   ---- ------------                            -----
                                    123 Smart Card Logon                        1.3.6.1.4.1.311.20.2.2
                                    101 Client Authentication                   1.3.6.1.5.5.7.3.2


PS G:\&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;False&lt;/strong&gt;, т.е. наш сертификат не прошёл проверку. Свойство &lt;a href="http://msdn.microsoft.com/en-us/library/aa377621(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;Certificate&lt;/strong&gt;s&lt;/a&gt; содержит все сертификаты в текущей цепочке. А метод &lt;a href="http://msdn.microsoft.com/en-us/library/aa377615(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;ApplicationPolicies()&lt;/strong&gt;&lt;/a&gt; показал Application Policies (в прошлом EKU). Ну и метод &lt;strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/aa377630(VS.85).aspx" target="_blank"&gt;Status()&lt;/a&gt;&lt;/strong&gt; вернул код ошибки. Все коды ошибок расписаны в описании самого метода. Т.е. ошибка 32 по табличке означает:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#0000ff"&gt;CAPICOM_TRUST_IS_UNTRUSTED_ROOT (&amp;H00000020) — The certificate or certificate chain is based on an untrusted root.&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Когда вышел &lt;strong&gt;Remote Desktop Connection 7.0&lt;/strong&gt; (который поставляется вместе с Windows 7), &lt;strong&gt;Александр Станкевич&lt;/strong&gt; (MVP: Enterprise Security) заметил очень плохую особенность с ним, а именно — рандомно пропал доступ к терминальным серверам, которые используют SSL для терминальных подключений. В ходе множества проверок было констатировано:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;цепочка завершалась на доверенном корневом сертификате (через просмотр сертификата); &lt;/li&gt;

  &lt;li&gt;CDP/AIA пути были валидные и CRL не были просрочены; &lt;/li&gt;

  &lt;li&gt;остальные параметры были сконфигурированы верно. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;RDP клиент мотивировал отказ в подключении следюущим: «RDP клиент не смог проверить сертификат на отзыв». Причём подключение с предыдущих версий RDC, а так же подключение к TS Web Access через IE было успешным. Как выяснилось на днях, причина была в том, что в новом RDC был изменён алгоритм certificate chaining engine и новая версия RDC больше не доверяла корневым сертификатам в пользовательском хранилище. Переустановка корневого сертификата в компьютерное хранилище решала проблему RDC 7. Но, как я говорил, в Windows 7/2008 R2 было изменено поведение certificate chaining engine в реализации X509Chain. Продемонстрирую небольшую табличку, которая покажет доверие пользовательским корневым сертификатам в CAPICOM и .NET реализациях certificate chaining engine для различных операционных систем:&lt;/p&gt;

&lt;table border="1" cellspacing="0" cellpadding="2" width="373" align="center"&gt;&lt;tbody&gt;
    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt; &lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;strong&gt;X509Chain (.NET)&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;strong&gt;CAPICOM.Chain (CryptoAPI)&lt;/strong&gt;&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt;&lt;strong&gt;Windows XP&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;img alt="Yes, of course!" src="/images/buttons/ok.png"&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt;&lt;strong&gt;Windows Server 2003&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;img alt="Yes, of course!" src="/images/buttons/ok.png"&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt;&lt;strong&gt;Windows Vista&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;img alt="Yes, of course!" src="/images/buttons/ok.png"&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt;&lt;strong&gt;Windows Server 2008&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;img alt="Yes, of course!" src="/images/buttons/ok.png"&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt;&lt;strong&gt;Windows 7&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;
    &lt;/tr&gt;

    &lt;tr&gt;
      &lt;td valign="middle" width="202"&gt;&lt;strong&gt;Windows Server 2008 R2&lt;/strong&gt;&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="68"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;

      &lt;td style="text-align: center" valign="middle" width="101"&gt;&lt;img alt="No!" src="/images/buttons/bad.png"&lt;/td&gt;
    &lt;/tr&gt;
  &lt;/tbody&gt;&lt;/table&gt;

&lt;blockquote&gt;
  &lt;p align="center"&gt;Таблица доверия пользовательскким корневым сертификатам различными движками построения цепочки сертификатов &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Следует учитывать, что различные приложения могут использовать свой движок для построения цепочек сертификатов, как &lt;strong&gt;RDC 7.0&lt;/strong&gt; и &lt;strong&gt;PKIView.msc&lt;/strong&gt; использует &lt;strong&gt;CAPICOM&lt;/strong&gt;, а &lt;strong&gt;PowerShell&lt;/strong&gt; — &lt;strong&gt;X509Chain&lt;/strong&gt;. Однако, у меня есть уверенность, что существует ещё одна реализация этого движка, которую использует &lt;strong&gt;Internet Explorer&lt;/strong&gt;. Это только мои догадки, но они основаны на том, что Internet Explorer (кроме Windows 7 и выше) использует пользовательский контейнер для проверки SSL веб-сайтов, т.е. по симптомам похоже на X509Chain. Однако, этот класс появился только в .Net Framework 2.0, которого, к примеру в оригинальной инсталляции Windows XP/2003 не было. Либо, как вариант, есть возможность настраивать этот момент в каждой реализации движка построения цепочек, но я пока не нашёл как. Это пока всё, что у меня есть по этому поводу.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=16ffa3d3-8449-4c16-9704-5d089b6a32e2"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,16ffa3d3-8449-4c16-9704-5d089b6a32e2.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
      <category>Security / PKI / Chaining Engine</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=b14ea574-ca90-4f1b-9845-35b6ce273fb2</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,b14ea574-ca90-4f1b-9845-35b6ce273fb2.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,b14ea574-ca90-4f1b-9845-35b6ce273fb2.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=b14ea574-ca90-4f1b-9845-35b6ce273fb2</wfw:commentRss>
      <slash:comments>18</slash:comments>
      <title>Certificate chaining engine в PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,b14ea574-ca90-4f1b-9845-35b6ce273fb2.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,b14ea574-ca90-4f1b-9845-35b6ce273fb2.aspx</link>
      <pubDate>Sat, 17 Oct 2009 20:51:59 GMT</pubDate>
      <description>&lt;div&gt;&lt;P&gt;Я предлагаю снова поговорить о certificate chaining engine, о котором мы уже говорили в посте &lt;A href="http://www.sysadmins.lv/PermaLink,guid,63f4fa92-f82b-4b01-a710-6324bae859bb.aspx"&gt;Certificate Chaining Engine — как это работает&lt;/A&gt; но в рамках его реализации в .NET и PowerShell. В Windows есть несколько реализаций этого chaining engine. Самые популярные:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx" target=_blank&gt;&lt;STRONG&gt;X509Chain&lt;/STRONG&gt;&lt;/A&gt;&lt;STRONG&gt; &lt;/STRONG&gt;
&lt;LI&gt;&lt;A href="http://msdn.microsoft.com/en-us/library/aa377611(VS.85).aspx" target=_blank&gt;&lt;STRONG&gt;CAPICOM.Chain&lt;/STRONG&gt;&lt;/A&gt; &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;CAPICOM — вещь несколько стрёмная и её лучше избегать. Тем более мне не удалось завести его в Vista/Windows 7. Реализация в .NET в виде &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.aspx" target=_blank&gt;&lt;STRONG&gt;X509Chain&lt;/STRONG&gt;&lt;/A&gt; ничуть не хуже, но, в то же время, проще. Итак, предлагаю начать с создания этого объекта с помощью &lt;STRONG&gt;New-Object&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] $chain = New-Object System.Security.Cryptography.X509Certificates.X509Chain
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain

                 ChainContext ChainPolicy                   ChainStatus                   ChainElements
                 ------------ -----------                   -----------                   -------------
                            0 System.Security.Cryptograp... {}                            {}


&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain | gm -membertype methods


   TypeName: System.Security.Cryptography.X509Certificates.X509Chain

Name        MemberType Definition
----        ---------- ----------
Build       Method     bool Build(System.Security.Cryptography.X509Certificates.X509Certificate2 certificate)
Equals      Method     bool Equals(System.Object obj)
GetHashCode Method     int GetHashCode()
GetType     Method     type GetType()
Reset       Method     System.Void Reset()
ToString    Method     string ToString()


&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/system.security.cryptography.x509certificates.x509chain.build.aspx" target=_blank&gt;&lt;STRONG&gt;Build()&lt;/STRONG&gt;&lt;/A&gt; и в качестве аргумента этот метод принимает только объекты &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx" target=_blank&gt;&lt;STRONG&gt;x509Certificate2&lt;/STRONG&gt;&lt;/A&gt;, а возвращать объект типа Boolean — &lt;STRONG&gt;True/False&lt;/STRONG&gt;. Объекты такого типа можно найти в провайдере Certififcates (просто выполнить &lt;STRONG&gt;dir cert:\store\container&lt;/STRONG&gt;) или импортировать из файла — &lt;A href="http://www.sysadmins.lv/PermaLink,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx"&gt;Импорт сертификатов в PowerShell&lt;/A&gt;. Но сначала мы посмотрим, что здесь можнол настроить. А настроить можно &lt;STRONG&gt;ChainPolicy&lt;/STRONG&gt;, представляющий собой объект &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chainpolicy.aspx" target=_blank&gt;&lt;STRONG&gt;X509ChainPolicy&lt;/STRONG&gt;&lt;/A&gt;. Эта политика позволяет задавать порядок проверки отзыва сертификатов, соответствие сертификата каким-то certificate policy, наличие определённых application policy (в прошлом известен нам как &lt;STRONG&gt;EKU&lt;/STRONG&gt; — &lt;EM&gt;Extended Key Usage&lt;/EM&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] $chain.ChainPolicy


ApplicationPolicy   : {}
CertificatePolicy   : {}
RevocationMode      : Online
RevocationFlag      : ExcludeRoot
VerificationFlags   : NoFlag
VerificationTime    : 17.10.2009 20:35:17
UrlRetrievalTimeout : 00:00:00
ExtraStore          : {}



&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;Revocation Mode&lt;/STRONG&gt;, который задаёт режим проверки отзыва и может иметь 3 вполне понятных значения, которые перечислены в &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509revocationmode.aspx" target=_blank&gt;&lt;STRONG&gt;X509RevocationMode&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;&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] [System.Enum]::GetNames([system.security.cryptography.x509certificates.x509revocationmode])
NoCheck
Online
Offline&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;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;NoCheck&lt;/STRONG&gt; — проверяет цепочку сертификатов без проверки на отзыв любых сертификатов в цепочке; 
&lt;LI&gt;&lt;STRONG&gt;Online&lt;/STRONG&gt; — проверяет сертификаты в цепочке скачивая новые списки CRL из свойства CDP сертификата, игнорируя локальный кеш CRL (используется по умолчанию, как это видно в просмотре свойств ChainPolicy) 
&lt;LI&gt;&lt;STRONG&gt;Offline&lt;/STRONG&gt; — проверяет сертификаты на отзыв с использованием кешированного CRL (если есть). &lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Если проверяем сертификаты на отзыв, то мы можем выбрать что именно будем проверять и этот выбор перечислен в &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509revocationflag.aspx" target=_blank&gt;&lt;STRONG&gt;X509RevocationFlag&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;&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] [System.Enum]::GetNames([system.security.cryptography.x509certificates.x509revocationflag])
EndCertificateOnly
EntireChain
ExcludeRoot&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;UL&gt;
&lt;LI&gt;&lt;STRONG&gt;EndCertificateOnly&lt;/STRONG&gt; — проверяет на отзыв только сам проверяемый сертификат. Остальные сертификаты в цепочке не проверяются; 
&lt;LI&gt;&lt;STRONG&gt;EntireChain&lt;/STRONG&gt; — проверяет на отзыв абсолютно все сертификаты в цепочке включая корневой сертификат. Правила хорошего тона диктуют нам не включать в корневой сертификат CA поля CDP и AIA, поскольку это лишено смысла и в большинстве случаев с этим флагом вы будете получать невалидную цепочку; 
&lt;LI&gt;&lt;STRONG&gt;ExcludeRoot&lt;/STRONG&gt; — проверяет на отзыв все сертификаты в цепочке, кроме корневого сертификата, что есть религионзно правильно и этот флаг установлен по умолчанию. &lt;/LI&gt;&lt;/UL&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] [System.Enum]::GetNames([system.security.cryptography.x509certificates.x509verificationflags])
NoFlag
IgnoreNotTimeValid
IgnoreCtlNotTimeValid
IgnoreNotTimeNested
IgnoreInvalidBasicConstraints
AllowUnknownCertificateAuthority
IgnoreWrongUsage
IgnoreInvalidName
IgnoreInvalidPolicy
IgnoreEndRevocationUnknown
IgnoreCtlSignerRevocationUnknown
IgnoreCertificateAuthorityRevocationUnknown
IgnoreRootRevocationUnknown
AllFlags&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/system.security.cryptography.x509certificates.x509verificationflags.aspx" target=_blank&gt;&lt;STRONG&gt;X509VerificationFlags&lt;/STRONG&gt;&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;&lt;FONT color=#ff0000&gt;&lt;STRONG&gt;Примечание:&lt;/STRONG&gt;&lt;/FONT&gt; эти флаги показывают что будет исключено из проверки, а не наоборот. По умолчанию проверяется всё (установлен &lt;STRONG&gt;NoFlag&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;&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] # правильный метод:
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $revflag = [System.Security.Cryptography.X509Certificates.X509RevocationFlag]::EndCertificateOnly
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainPolicy.RevocationFlag = $revflag
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainPolicy


ApplicationPolicy   : {}
CertificatePolicy   : {}
RevocationMode      : Online
RevocationFlag      : EndCertificateOnly
VerificationFlags   : NoFlag
VerificationTime    : 17.10.2009 20:35:17
UrlRetrievalTimeout : 00:00:00
ExtraStore          : {}



&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] # неправильный метод, но мне он нравится
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainPolicy.RevocationFlag = "excluderoot"
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainPolicy


ApplicationPolicy   : {}
CertificatePolicy   : {}
RevocationMode      : Online
RevocationFlag      : ExcludeRoot
VerificationFlags   : NoFlag
VerificationTime    : 17.10.2009 20:35:17
UrlRetrievalTimeout : 00:00:00
ExtraStore          : {}



&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;В принципе, все эти enumeration можно просто указывать в виде строки, а PowerShell уже сам подобъёт его под нужный тип.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Примечание:&lt;/FONT&gt;&lt;/STRONG&gt; флаги проверки на отзыв можно указывать только по одному, а флаги исключений можно перечислять через запятую. Это видно по названию класса: если класс указан в единственном числе (X509RevocationFlag), то и значение можно указать только одно, а если во множественном числе (X509VerificationFlags), то их можно указать несколько через запятую.&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;&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $valid = (dir cert:\currentuser\my)[1]
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $invalid = (dir cert:\currentuser\my)[0]
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.Build($valid)
True
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainElements | select -expand certificate

Thumbprint                                Subject
----------                                -------
986D375362652FE9E39BA4D042A6B8BA75745998  CN=Administrator, CN=Users, DC=sysadmins, DC=lv
E82ACC45841280DDEAB9F7847418FA26354457A7  CN=sysadmins-LV-CA, DC=sysadmins, DC=lv


&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;img alt=":)" src="/smilies/happy.gif"&gt;). Метод &lt;STRONG&gt;Build()&lt;/STRONG&gt; вернул True, что означает успешную проверку всей цепочки моего сертификата до доверенного корня. А вот что случилось с сертификатом билайна:&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] $chain.reset()
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.Build($invalid)
False
&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainElements | select -expand certificate

Thumbprint                                Subject
----------                                -------
EB74DA32E865C78FCB853DDA5FE45962098E1B3B  CN=trust.beeline.ru, OU=DIT, O=Vimpelcom, L=Moscow, S=Moscow, C=RU


&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainStatus

                                                     Status StatusInformation
                                                     ------ -----------------
                                               PartialChain Sertificesanas kedi nevareja veidot pie uzticamas saknes...
                                    RevocationStatusUnknown Atsauksanas funkcija nevareja parbaudit sertifikata atsa...
                                          OfflineRevocation Atsauksanas funkcija nevareja parbaudit atsauksanu, jo a...


&lt;FONT color=#ff0000&gt;[↓]&lt;/FONT&gt; [vPodans] $chain.ChainStatus | %{$_.statusinformation.trim()}
Sertificesanas kedi nevareja veidot pie uzticamas saknes iestades.
Atsauksanas funkcija nevareja parbaudit sertifikata atsauksanu.
Atsauksanas funkcija nevareja parbaudit atsauksanu, jo atsauksanas serveris bija bezsaiste.
&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;Поскольку при каждой проверке сертификаты в ChainElements накапливаются, то после каждой проверки следует очищать объект методом &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.reset.aspx" target=_blank&gt;&lt;STRONG&gt;Reset()&lt;/STRONG&gt;&lt;/A&gt;. Как и следовало ожидать, сертификат билайна вернул False, показывая, что цепочка у этого сертификата имеет проблемы. В случае неуспешной проверки, будет заполняться свойство &lt;A href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509chain.chainstatus.aspx" target=_blank&gt;&lt;STRONG&gt;ChainStatus&lt;/STRONG&gt;&lt;/A&gt;. Данное свойство содержит все ошибки, которые были костатированы при проверке цепочки. Для меня пока непонятным стал факт, что ошибки он написал на латышском языке, хотя я его об этом не просил. Откуда он это взял — непонятно, но он сказал, что не смог построить цепочку до доверенного корня и функция проверки отзыва провалилась по всем статьям, поскольку пути в CDP сертификата нерабочие.&lt;/P&gt;
&lt;P&gt;&lt;STRONG&gt;&lt;FONT color=#ff0000&gt;Примечание:&lt;/FONT&gt;&lt;/STRONG&gt; обязательно следует учитывать тот факт, что при построении цепочки сертификатов и проверке доверия класс X509Chain в Windows 7 и Windows Server 2008 R2 работает в контексте &lt;STRONG&gt;LocalSystem&lt;/STRONG&gt; и всегда игнорирует пользовательские контейнеры &lt;STRONG&gt;Trusted Root Certification Authorities&lt;/STRONG&gt;. Поэтому если корень цепочки не заканчивается на одном из сертификатов &lt;STRONG&gt;Trusted Root CAs&lt;/STRONG&gt; хранилища &lt;STRONG&gt;LocalMachine&lt;/STRONG&gt;, то цепочка будет считаться недоверенной. Для предыдущих ОС цепочка может заканчиваться на пользовательском хранилище &lt;STRONG&gt;Current User&lt;/STRONG&gt;.&lt;/P&gt;
&lt;P&gt;В принципе это всё, что вам следует знать про реализацию certificate chaining engine в .NET и его использование в PowerShell. В качестве бонуса прилагаю скрипт для проверки цепочки сертификатов:&lt;/P&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; Test-Certificate.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; Passes certificate through certificate chaining engine&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt;
#
#&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; Vadims Podans (c) 2009&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;Test-Certificate&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: #800080"&gt;$true&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, ValueFromPipeline &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;$true&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, Position &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;$Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
        [&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008080"&gt;System.Security.SecureString&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;]&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Password&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
        [ValidateSet(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;NoCheck&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Online&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Offline&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&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;$CRLMode&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Online&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
        [ValidateSet(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;EndCertificateOnly&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;EntireChain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;ExcludeRoot&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&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;$CRLFlag&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;ExcludeRoot&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
        [ValidateSet(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;AllFlags&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;AllowUnknownCertificateAuthority&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;NoFlag&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreNotTimeValid&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreCtlNotTimeValid&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreNotTimeNested&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreInvalidBasicConstraints&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreWrongUsage&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreInvalidName&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreInvalidPolicy&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreEndRevocationUnknown&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreCtlSignerRevocationUnknown&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreCertificateAuthorityRevocationUnknown&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;,
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;IgnoreRootRevocationUnknown&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&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;$VerificationFlags&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;NoFlag&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
    )
    
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;begin&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; создаём объекты X509Certificate2 и X509chain ещё до поступлениея первого объекта сертификата&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="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;$chain&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.X509Chain&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; в X509Chain записываем параметры проверки сертификатов. Как критерии&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: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;ChainPolicy&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;RevocationFlag&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;$CRLFlag&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;ChainPolicy&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;RevocationMode&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;$CRLMode&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;ChainPolicy&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;VerificationFlags&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;$VerificationFlags&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: #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;function&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0"&gt;_getstatus_&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: #800080"&gt;$chain&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: #0000ff"&gt;if&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: #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;Current&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;certificate&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;SerialNumber&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;and&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;revocation&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;status&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;is&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;valid&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; COLOR: #5f9ea0"&gt;-ForegroundColor&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Green&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
            } &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;else&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Current certificate $($cert.SerialNumber) chain is invalid due of the following errors:&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
                &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;ChainStatus&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: #5f9ea0; FONT-WEIGHT: bold"&gt;Write-Host&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$_&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.StatusInformation.trim() &lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; COLOR: #5f9ea0"&gt;-ForegroundColor&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Red&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;}
            }
        }
    }
    
    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;process&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; если аргумент сертификата уже является объектом X509Certificate2, то&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: #0000ff"&gt;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$_&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;-is&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; [&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008080"&gt;System.Security.Cryptography.X509Certificates.X509Certificate2&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: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;Build&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$_&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
            &lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0"&gt;_getstatus_&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: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$_&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
        } &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;else&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; если аргумент не является объектом X509Certificate2, то это будет путь к файлу&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: #0000ff"&gt;if&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;Test-Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Certificate&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Specified path is invalid&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&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: #0000ff"&gt;else&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: #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;if&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; ((&lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0; FONT-WEIGHT: bold"&gt;Resolve-Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;).Provider.Name &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;-ne&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;FileSystem&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Spicifed path is not recognized as filesystem path. Try again&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&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: #0000ff"&gt;else&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: #800080"&gt;$Certificate&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;gi&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; $(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0; FONT-WEIGHT: bold"&gt;Resolve-Path&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Certificate&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; и на основании расширения файла через Switch преобразуем файл в&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; X509Certificate2 объект или объекты&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;switch&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #ff0000"&gt;-regex&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; (&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.Extension) {
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;\.CER|\.DER|\.CRT&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&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;Import&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.FullName)}
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;\.PFX&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&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: #ff0000"&gt;!&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Password&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;) {&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Password&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;Read-Host&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Enter password for PFX file $certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="FONT-STYLE: italic; COLOR: #5f9ea0"&gt;-AsSecureString&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: #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: #008000"&gt;#&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; по причине отсутствия подходящего конструктора метода Import(), чтобы&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; можно было указать только путь к файлу и пароль от PFX&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: #8b4513"&gt;Import&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.FullName, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$password&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;, &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;UserKeySet&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
                        }
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;\.P7B|\.SST&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&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="COLOR: #800000"&gt;System.Security.Cryptography.X509Certificates.X509Certificate2Collection&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: #008080"&gt;system.IO.File&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;]::&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;ReadAllBytes&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$file&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.FullName))
                        }
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #0000ff"&gt;default&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;"&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;Looks like your specified file is not a certificate file&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&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: #008000"&gt;#&lt;/SPAN&gt;&lt;SPAN style="COLOR: #008000"&gt; полученный объект или объекты сертификатов пропускаем через метод Build() и вызываем&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: #800080"&gt;$cert&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;$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: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;Build&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;(&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$_&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;)
                        &lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0"&gt;_getstatus_&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: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&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: #800080"&gt;$cert&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;Reset&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;()
                    &lt;/SPAN&gt;&lt;SPAN style="COLOR: #800080"&gt;$chain&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;.&lt;/SPAN&gt;&lt;SPAN style="COLOR: #8b4513"&gt;Reset&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;()
                }
            }
        }
    }
}&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Данный скрипт может принимать аргументы в виде уже готовых объектов X509Certificate2 или с указанием пути к файлу сертификата, например:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;&lt;PRE&gt;&lt;SPAN style="COLOR: #5f9ea0; FONT-WEIGHT: bold"&gt;dir&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; cert:\&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;currentuser\my&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; | &lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0"&gt;Test-Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt;
&lt;/SPAN&gt;&lt;SPAN style="COLOR: #5f9ea0"&gt;Test-Certificate&lt;/SPAN&gt;&lt;SPAN style="COLOR: #000000"&gt; .\&lt;/SPAN&gt;&lt;SPAN style="COLOR: #800000"&gt;mycert.cer&lt;/SPAN&gt;&lt;/PRE&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Ну и при желании можно поуказывать там разные параметры и флаги проверки.&lt;/P&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=b14ea574-ca90-4f1b-9845-35b6ce273fb2"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,b14ea574-ca90-4f1b-9845-35b6ce273fb2.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
      <category>Security / PKI / Chaining Engine</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=289efb4c-376a-435a-95a5-5a3e46ce7ce5</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,289efb4c-376a-435a-95a5-5a3e46ce7ce5.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,289efb4c-376a-435a-95a5-5a3e46ce7ce5.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=289efb4c-376a-435a-95a5-5a3e46ce7ce5</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Certificate management pack</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,289efb4c-376a-435a-95a5-5a3e46ce7ce5.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,289efb4c-376a-435a-95a5-5a3e46ce7ce5.aspx</link>
      <pubDate>Mon, 14 Sep 2009 19:02:32 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Представлю на обозрение пробный скрипт по управлению сертификатами в хранилище Certificate Store — &lt;strong&gt;CertMgmtPack.ps1&lt;/strong&gt;, который (как я надеюсь) может найти применение на серверах Windows Server 2008 R2 Server Core и реализован на основе наших недавних исследований:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx"&gt;Простой экспорт сертификатов в PowerShell&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx"&gt;Сложный экспорт сертификатов в PowerShell&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx"&gt;Импорт сертификатов в PowerShell&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,ca62f1b3-ca7f-43cb-a4b2-948194adbc74.aspx"&gt;Экспорт PFX с удалением ключа из хранилища в PowerShell&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;Версия пока что 0.47 (т.к. предстоит добавить ещё разного функционала и допилить существующий). Пока что мне удалось реализовать функционал импорта сертификатов из файлов в store и экспорт из store в файлы сертификатов.&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/CertMgmtPack.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/CertMgmtPack.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/CertMgmtPack.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;15,8 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/CertMgmtPack.ps1" target="_self" alt="Download File"&gt;CertMgmtPack.ps1&lt;/a&gt; &lt;/span&gt;&lt;/p&gt; &lt;/div&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; скрипт работает только в PowerShell V2. В каждую функцию вложена справка, которую вы можете прочитать набрав Get-Help Import/Export-Certiifcate.&lt;/p&gt;  &lt;p&gt;После подключения скрипта (используя dot-sourcing) у вас будут доступны 2 функции:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;Export-Certificate &lt;/strong&gt;&lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Import-Certificate&lt;/strong&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;И пару слов о том, как их использовать.&lt;/p&gt;  &lt;h4 align="center"&gt;Import-Certificate&lt;/h4&gt;  &lt;p&gt;содержит следующие параметры:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;font color="#0000ff"&gt;Path &amp;lt;String&amp;gt;&lt;/font&gt; — путь к файлу сертификата, который может иметь следующий набор расширений: &lt;strong&gt;CER&lt;/strong&gt;, &lt;strong&gt;DER&lt;/strong&gt;, &lt;strong&gt;PFX&lt;/strong&gt;, &lt;strong&gt;P7B&lt;/strong&gt;, &lt;strong&gt;SST&lt;/strong&gt;. Распознавание типов сертификатов осуществляется по расширению файла. Данная функция может принимать параметр пути из конвейера следующим путём:       &lt;pre&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;dir&lt;/span&gt;&lt;span style="color: #000000"&gt; *.cer | &lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;Import-Certificate&lt;br /&gt;&lt;/span&gt;&lt;/pre&gt;
Параметр обязательный. &lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;font color="#0000ff"&gt;Password &amp;lt;SecureString&amp;gt;&lt;/font&gt; — пароль для PFX файла. Пароль не требуется для остальных типов файлов. Однако, хочу предупредить, что пароли не принимаются в открытом виде, а должны передаватьсякак &lt;strong&gt;SecureString&lt;/strong&gt;. Это можно реализовать различными способами, например, вот так: 

    &lt;pre&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Read-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;Enter password for PFX file&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="font-style: italic; color: #5f9ea0"&gt;–AsSecureString&lt;/span&gt;&lt;/pre&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;font color="#0000ff"&gt;Storage &amp;lt;String&amp;gt;&lt;/font&gt; — указывает контекст импорта сертификата, т.е. это будет хранилище текущего пользователя (по умолчанию) или в хранилище компьютера (требуются права локального администратора). Может принимать значения &lt;strong&gt;User&lt;/strong&gt; или &lt;strong&gt;Computer&lt;/strong&gt;. Если параметр не указан, то берётся значение по умолчанию — &lt;strong&gt;User&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Container &amp;lt;String&amp;gt;&lt;/font&gt; — указывает контейнер размещения сертификата. Это может быть один из: &lt;strong&gt;AuthRoot&lt;/strong&gt;, &lt;strong&gt;CA&lt;/strong&gt;, &lt;strong&gt;Disallowed&lt;/strong&gt;, &lt;strong&gt;My&lt;/strong&gt; (&lt;em&gt;по умолчанию&lt;/em&gt;), &lt;strong&gt;REQUEST&lt;/strong&gt;, &lt;strong&gt;Root&lt;/strong&gt;, &lt;strong&gt;SmartCardRoot&lt;/strong&gt;, &lt;strong&gt;Trust&lt;/strong&gt;, &lt;strong&gt;TrustedPeople&lt;/strong&gt;, &lt;strong&gt;TrustedPublisher&lt;/strong&gt;, &lt;strong&gt;UserDS&lt;/strong&gt;. Расшифровка контейнеров (сопоставление названиям в оснастке CertMgr.msc) приведена внутри скрипта в хелпе функции. Если параметр не указан, то применяется параметр по умолчанию — &lt;strong&gt;My&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Exportable &amp;lt;Switch&amp;gt;&lt;/font&gt; — применяется только для импорта PFX файлов. Данный ключ помечает импортируемый сертификат как экспортируемый. Это означает, что вы после процедуры импорта сможете снова экспортировать сертификат с закрытым ключом. Эсли ключ Exportable не указан, то закрытый ключ сертификата не помечается как экспортируемый и при экспорте у вас не будет возможности экспортировать закрытый ключ данного сертификата. &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;StrongProtection &amp;lt;Switch&amp;gt;&lt;/strong&gt; — применяется только для импорта PFX файлов. Данный ключ включает режим усиленной защиты закрытого ключа PFX файла. Это означает, что для каждой попытки использования закрытого ключа от этого сертификата потребуется ручной ввод пароля. &lt;font color="#ff0000"&gt;Данный ключ нельзя использовать, если Storage указан как Computer&lt;/font&gt;, поскольку компьютерные сертификаты не поддерживают такой режим. Это связано с тем, что компьютерные сертификаты используются в контексте учётной записи LocalSystem и lsass.exe не предоставляет пользователю UI для ввода пароля. В любом случае, если вы попробуете это сделать, скрипт выдаст соответствующую ошибку и импорт произведён не будет. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;И пару примеров, как использовать функцию:&lt;/p&gt;

&lt;pre&gt;&lt;span style="color: #800080"&gt;$pass&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;Read-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;Enter password for PFX&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="font-style: italic; color: #5f9ea0"&gt;–AsSecureString&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #5f9ea0"&gt;Import-Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;mycert.pfx&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Password&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$pass&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Exportable&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;импортирует файл mycert.pfx в контейнер Personal хранилища текущего пользователя и пометит ключ как экспортируемый.&lt;/p&gt;

&lt;pre&gt;&lt;span style="color: #5f9ea0"&gt;Import-Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;mycert.pfx&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Password&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$pass&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-StrongProtection&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Импортирует файл mycert.pfx в контейнер Personal хранилища текущего пользователя, пометит ключ как неэкспортируемый и включит режим усиленной защиты закрытого ключа, что потребует ввод пароля пользователя каждый раз при его использовании.&lt;/p&gt;

&lt;pre&gt;&lt;span style="color: #5f9ea0"&gt;Import-Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;certs.p7b&lt;/span&gt;&lt;span style="color: #000000"&gt; –&lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;Storage&lt;/span&gt;&lt;span style="color: #000000"&gt; '&lt;/span&gt;&lt;span style="color: #800000"&gt;Computer'&lt;/span&gt;&lt;span style="color: #000000"&gt; –&lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;Container&lt;/span&gt;&lt;span style="color: #000000"&gt; '&lt;/span&gt;&lt;span style="color: #800000"&gt;TrustedPublisher'&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Импортирует все сертификаты из файла certs.p7b в контейнер Trusted Publishers компьютерного хранилища.&lt;/p&gt;

&lt;h4 align="center"&gt;Экспорт сертификатов&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;font color="#0000ff"&gt;Path &amp;lt;String&amp;gt;&lt;/font&gt; — указывает путь к папке (не к файлу!), в которую будут экспортированы все указанные сертификаты. Парамер обязателен. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Type &amp;lt;String&amp;gt;&lt;/font&gt; — указывает тип экспортируемых сертификатов. Может принимать одно из значений: &lt;strong&gt;CERT&lt;/strong&gt;, &lt;strong&gt;PFX&lt;/strong&gt;, &lt;strong&gt;PKCS12&lt;/strong&gt;, &lt;strong&gt;PKCS7&lt;/strong&gt;, &lt;strong&gt;SST&lt;/strong&gt; (&lt;em&gt;Serialized Store&lt;/em&gt;). Параметр так же обязателен. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Password &amp;lt;SecureString&amp;gt;&lt;/font&gt; — задаёт пароль для экспортируемых PFX файлов (в качестве типа экспортируемых сертификатов указано PFX или PKCS12 и является для них обязательным). Параметр не принимает значение в виде простой строки, а только &lt;strong&gt;SecureString&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Storage &amp;lt;String&amp;gt;&lt;/font&gt; — указывает контекст поиска экспортируемых сертификатов, т.е. поиск будет производиться в компьютерном хранилище или хранилище текущего пользователя (по умолчанию). Может принимать значения &lt;strong&gt;CurrentUser&lt;/strong&gt; или &lt;strong&gt;LocalMachine&lt;/strong&gt;. Если параметр не указан, то берётся значение по умолчанию — &lt;strong&gt;User&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Container &amp;lt;String&amp;gt;&lt;/font&gt; — указывает контейнер размещения сертификата (или сертификатов). Это может быть один из: &lt;strong&gt;AuthRoot&lt;/strong&gt;, &lt;strong&gt;CA&lt;/strong&gt;, &lt;strong&gt;Disallowed&lt;/strong&gt;, &lt;strong&gt;My&lt;/strong&gt; (&lt;em&gt;по умолчанию&lt;/em&gt;), &lt;strong&gt;REQUEST&lt;/strong&gt;, &lt;strong&gt;Root&lt;/strong&gt;, &lt;strong&gt;SmartCardRoot&lt;/strong&gt;, &lt;strong&gt;Trust&lt;/strong&gt;, &lt;strong&gt;TrustedPeople&lt;/strong&gt;, &lt;strong&gt;TrustedPublisher&lt;/strong&gt;, &lt;strong&gt;UserDS&lt;/strong&gt;. Расшифровка контейнеров (сопоставление названиям в оснастке CertMgr.msc) приведена внутри скрипта в хелпе функции. Если параметр не указан, то поиск производится в контейнере по умолчанию — &lt;strong&gt;My&lt;/strong&gt;. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Thumbprint &amp;lt;String&amp;gt;&lt;/font&gt; — задаёт критерий поиска сертификатов по отпечатку ключа (соответствующее поле Thumbprint сертификата). Можно указывать как полный отпечаток, так и любую его часть. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Subject &amp;lt;String&amp;gt;&lt;/font&gt; — задаёт критерий поиска сертификатов по полю Subject. Можно указывать как полный Subject, так и любую его часть. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;Issuer &amp;lt;String&amp;gt;&lt;/font&gt; — задаёт критерий поиска по конкретному издателю сертификата. Можно указывать как полный CN издателя, так и любую его часть. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;SerialNumber &amp;lt;String&amp;gt;&lt;/font&gt; — задаёт критерий поиска по серийному номеру сертификата. Можно указывать как точный серийный номер, так и любую его часть. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;NotAfter &amp;lt;String&amp;gt;&lt;/font&gt; — задаёт критерий поиска по дате истечения сертификата. Дата задаётся в формате &lt;strong&gt;dd.MM.yyyy&lt;/strong&gt; (&lt;em&gt;день.месяц.год&lt;/em&gt;). В результате использования этого параметра будут отобраны сертификаты, которые истекут не позднее указанной даты. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;NotBefore &amp;lt;String&amp;gt;&lt;/font&gt; — задаёт критерий поиска по дате начала действия сертификате. Как и в NotAfter дата указывается в формате &lt;strong&gt;dd.MM.yyyy&lt;/strong&gt; и в результате использования этого параметра будут отобраны сертификаты, действие которых начинается не раньше указанной даты. &lt;/li&gt;

  &lt;li&gt;&lt;font color="#0000ff"&gt;DeleteKey &amp;lt;Swtich&amp;gt;&lt;/font&gt; — используется только при экспорте сертификатов вместе с закрытыми ключами в PFX файлы. Данный ключ при успешном экспорте удаляет закрытый ключ данного сертификата из хранилища. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Я не смог провести полноценное тестирование функции экспорта, поэтому гарантировать 100% работу пока не могу. Но вы, уважаемые читатели, можете мне в этом помочь.&lt;/p&gt;

&lt;p&gt;И несколько примеров использования:&lt;/p&gt;

&lt;pre&gt;&lt;span style="color: #5f9ea0"&gt;Export-Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;c:\certs&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Type&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;PKCS7&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Экспортирует все сертификаты из Current User\Personal в один PKCS7 файл с именем &lt;strong&gt;ExportedCertificates.p7b&lt;/strong&gt; (это имя зашито на уровне скрипта).&lt;/p&gt;

&lt;pre&gt;&lt;span style="color: #5f9ea0"&gt;Export-Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;c:\certs&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Type&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;cert&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Storage&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'LocalMachine&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Container&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;Root&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-SerialNumber&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;663&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Экспортирует все сертификаты из контейнера доверенных центров сертификации (Trusted Root CAs) компьютерного хранилища, у которых в серийном номере встречается последовательность 663 в CER файлы. При этом каждый сертификат будет экспортирован в индивидуальный файл с именем, которое строится по схеме: &lt;font color="#008000"&gt;SubjectCN_Thumprint.CER&lt;/font&gt;, например: &lt;font color="#0000ff"&gt;Thawte Premium Server CA_4F65566336DB6598581D584A596C87934D5F2AB4.cer&lt;/font&gt;&lt;/p&gt;

&lt;pre&gt;&lt;span style="color: #5f9ea0"&gt;Export-Certificate&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;c:\certs&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Type&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;PKCS12&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Password&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$pass&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-DeleteKey&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Subject&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;UserName&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;/pre&gt;

&lt;p&gt;Экспортирует все сертификаты из Current User\Personal в PFX файлы у которых в любом месте поля Subject есть UserName. При успешном экспорте закрытый ключ сертификата будет удалён из хранилища и будет содержаться только в PFX файле.&lt;/p&gt;

&lt;p&gt;В связи с тем, что CN поля Subject может содержать недопустимые символы для имён файлов, мне скорее всего придётся искать другой метод именования экспортируемых сертификатов и чтобы они были распознаваемые. Если вы обнаружите какие-то ошибки или будут пожелания, то пишите мне в коментарии или на почту. По мере дописывания я буду выкладывать новые версии скрипта.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=289efb4c-376a-435a-95a5-5a3e46ce7ce5"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,289efb4c-376a-435a-95a5-5a3e46ce7ce5.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=ca62f1b3-ca7f-43cb-a4b2-948194adbc74</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,ca62f1b3-ca7f-43cb-a4b2-948194adbc74.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,ca62f1b3-ca7f-43cb-a4b2-948194adbc74.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=ca62f1b3-ca7f-43cb-a4b2-948194adbc74</wfw:commentRss>
      <slash:comments>2</slash:comments>
      <title>Экспорт PFX с удалением ключа из хранилища в PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,ca62f1b3-ca7f-43cb-a4b2-948194adbc74.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,ca62f1b3-ca7f-43cb-a4b2-948194adbc74.aspx</link>
      <pubDate>Thu, 10 Sep 2009 19:07:54 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Короткая заметка. Когда вы экспортируете сертификат вместе с закрытым ключом, то можете заметить такую опцию:&lt;/p&gt;  &lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Delete the Private key if the export is successful" border="0" alt="Delete the Private key if the export is successful" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PFXPowerShell_122AC/Capture.png" width="517" height="470" /&gt; &lt;/p&gt;  &lt;p&gt;К сожалению, метод &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.export.aspx" target="_blank"&gt;Export()&lt;/a&gt; у объектов &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx" target="_blank"&gt;X509Certificate2&lt;/a&gt; не позволяет штатно проделывать данную операцию. Это можно сделать через &lt;a href="http://msdn.microsoft.com/en-us/library/aa387359(VS.85).aspx" target="_blank"&gt;CAPICOM.PrivateKey.Delete()&lt;/a&gt;, но данная возможность отсутствует в PowerShell, в то время, как вы можете это сделать в VBS. Это связано с весьма паршивой поддержкой COM со стороны PowerShell, поэтому для реализации функционала этой галочки вам придётся проделать следующие шаги:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;Получить объект X509Certificate2 самого сертификата; &lt;/li&gt;    &lt;li&gt;Экспортировать его в PFX; &lt;/li&gt;    &lt;li&gt;Открыть хранилище в режиме ReadWrite; &lt;/li&gt;    &lt;li&gt;Удалить данный сертификат из хранилища; &lt;/li&gt;    &lt;li&gt;Экспортировать объект сертификата уже не в PFX, а в Cert; &lt;/li&gt;    &lt;li&gt;Импортировать этот экспортированный объект Cert (хотя, на самом деле там будет массив байтов, но это не столь существенно). &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;На языке PowerShell это выглядеть будет примерно так:&lt;/p&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: #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;dir&lt;/span&gt;&lt;span style="color: #000000"&gt; cert:\&lt;/span&gt;&lt;span style="color: #800000"&gt;currentuser\my&lt;/span&gt;&lt;span style="color: #000000"&gt;)[0]
&lt;/span&gt;&lt;span style="color: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; записываем пароль для PFX файла&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$pass&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;Read-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;Password&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="font-style: italic; color: #5f9ea0"&gt;-AsSecureString&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; экспортируем его в PFX формат&lt;/span&gt;&lt;span style="color: #008000"&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;.Export(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;pfx&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;$pass&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;System.IO.File&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;WriteAllBytes&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;mycert.pfx&lt;/span&gt;&lt;span style="color: #800000"&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: #008000"&gt;#&lt;/span&gt;&lt;span style="color: #008000"&gt; снова экспортируем данный объект, но уже в Cert формат&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$tempcert&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;.Export(&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;span style="color: #800000"&gt;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: #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;$store&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.X509Store&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;my&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;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: #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;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Open([&lt;/span&gt;&lt;span style="color: #008080"&gt;System.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: #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;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Remove(&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; записываем обратно Cert объект в хранилище, теперь уже без закрытого ключа&lt;/span&gt;&lt;span style="color: #008000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$tempcert&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #800080"&gt;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Close()&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Это только образец кода и его не стоит использовать прямо в таком виде, т.к. вы должны точно убедиться, что у вас PFX файл создался и он валидный. В противном случае вы останетесь совсем без закрытого ключа. И ещё раз напоминаю, при работе с хранилищем – не забывайте его закрывать после работы.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=ca62f1b3-ca7f-43cb-a4b2-948194adbc74"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,ca62f1b3-ca7f-43cb-a4b2-948194adbc74.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=9932bca2-6f85-4ed5-b001-32a37b67b146</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=9932bca2-6f85-4ed5-b001-32a37b67b146</wfw:commentRss>
      <title>Импорт сертификатов в PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx</link>
      <pubDate>Wed, 09 Sep 2009 19:20:18 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;В предыдущих статьях мы с вами уже изучили методы экспорта сертификатов из хранилища Certificate Store в файл:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx"&gt;Простой экспорт сертификатов в PowerShell&lt;/a&gt; &lt;/li&gt;    &lt;li&gt;&lt;a href="http://www.sysadmins.lv/PermaLink,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx"&gt;Сложный экспорт сертификатов в PowerShell&lt;/a&gt; &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;а так же рассмотрели сопутствующие вопросы. Теперь же предлагаю рассмотреть обратную операцию – добавление сертификатов в cert store из файлов. Этот процесс будет несколько легче, чем экспорт, поэтому я в одном посте покажу импорт всех типов сертификатов (они все используют одну схему).&lt;/p&gt;  &lt;p&gt;Для импорта нам потребуется метод &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.import(VS.85).aspx" target="_blank"&gt;x509Certificate.Import()&lt;/a&gt;, который так же как и метод &lt;strong&gt;Export()&lt;/strong&gt; имеет несколько конструкторов. Мы можем выбрать один универсальный, который подойдёт нам для всех типов файлов сертификатов и это будет конструктор: &lt;a href="http://msdn.microsoft.com/en-us/library/ms148441(VS.85).aspx" target="_blank"&gt;X509Certificate2.Import Method (String, SecureString, X509KeyStorageFlags)&lt;/a&gt;. В качестве аргументов он принимает следующее:&lt;/p&gt;  &lt;ul&gt;   &lt;li&gt;&lt;strong&gt;String&lt;/strong&gt; – путь к файлу сертификата &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;SecureString&lt;/strong&gt; – строка с паролем. Требуется только для импорта PFX сертификатов, т.к. остальные типы файлов не содержат закрытых ключей и защищать их паролем нет смысла. Если это не PFX, то значение этого аргумента просто выставляется в $null. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;объект типа &lt;/strong&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509keystorageflags(VS.85).aspx" target="_blank"&gt;&lt;strong&gt;X509KeyStorageFlags&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;DefaultKeySet&lt;/strong&gt; – указывает, что сертификат предназначен для импорта в контейнер Personal хранилища CurrentUser (дефолт). &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;Exportable&lt;/strong&gt; – используется только для PFX файлов и говорит, будет ли возможность экспортировать сертификат с закрытым ключом. Если мы этот флаг не указываем, то после импорта не будет возможности снова экспортировать в PFX файл. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;MachineKeySet&lt;/strong&gt; – указывает, что сертификат будет установлен в хранилище компьютера (LocalSystem). &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;PersistKeySet&lt;/strong&gt; – используется только для PFX и сохраняет пароль от PFX файла в сертификате. Данный пароль будет использован при дальнейшем экспорте в PFX файл (будет работать только с флагом Exportable). &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;UserKeySet&lt;/strong&gt; – указывает, что сертификат будет установлен в пользовательское хранилище. &lt;/li&gt;    &lt;li&gt;&lt;strong&gt;UserProtected&lt;/strong&gt; – используется только для PFX файлов и для пользовательских сертификатов. Этот флаг включает Private Key Strong Protection, который при каждом использовании закрытого ключа будет требовать ввода пароля. &lt;/li&gt; &lt;/ul&gt;  &lt;p&gt;&lt;strong&gt;&lt;font color="#ff0000"&gt;Примечание:&lt;/font&gt;&lt;/strong&gt; вы никогда не должны использовать флаг &lt;strong&gt;UserProtected&lt;/strong&gt; для компьютерных сертификатов, поскольку они используются в контексте &lt;strong&gt;LocalSystem&lt;/strong&gt; и у вас просто не будет возможности ввести пароль для использования этого закрытого ключа.&lt;/p&gt;  &lt;p&gt;Т.к. &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509keystorageflags(VS.85).aspx" target="_blank"&gt;X509KeyStorageFlags&lt;/a&gt; на самом деле является перечислителем (enumerator), то создавать его объект не обязательно и флаги можно просто использовать как строки. PowerShell уже сам подобъёт эти флаги к нужному типу данных.&lt;/p&gt;  &lt;p&gt;т.к. у нас ещё нет готового объекта сертификатов, то мы его просто создаём:&lt;/p&gt;  &lt;blockquote&gt;   &lt;pre&gt;&lt;span style="color: #800080"&gt;$certs&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;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;И в этом объекте у нас будет метод &lt;strong&gt;Import()&lt;/strong&gt;, которым мы уже воспользуемся:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$path&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;mycert.pfx&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;$password&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;Read-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;Type password for PFX certificate&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="font-style: italic; color: #5f9ea0"&gt;-AsSecureString&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$flags&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;UserKeySet, Exportable&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;$certs&lt;/span&gt;&lt;span style="color: #000000"&gt;.Import(&lt;/span&gt;&lt;span style="color: #800080"&gt;$path&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$password&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$flags&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Обратите внимание, что вы за один раз можете указать несколько флагов для &lt;strong&gt;KeyStorage&lt;/strong&gt;, просто перечислив их через запятую. Теперь $certs у нас содержит x509Certificate2 объект нашего сертификата:&lt;/p&gt;

&lt;div style="width: 915px"&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] $certs = New-Object system.security.cryptography.x509certificates.x509certificate2
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $path = &amp;quot;mycert.pfx&amp;quot;
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $password = Read-Host &amp;quot;Type password for PFX certificate&amp;quot; -AsSecureString
Type password for PFX certificate: *
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $flags = &amp;quot;UserKeySet, Exportable&amp;quot;
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $certs.Import($path, $password, $flags)
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $certs

Thumbprint                                Subject
----------                                -------
0F5157A8342C66493E7B1354530DD7A9F980BC69  CN=vPodans


&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;как видите, у нас всё случилось, PFX файл был успешно прочитан и помещён в объект x509Certificate2. Но это только половина дела, поскольку этот сертификат пока существует только самом в объекте, но не в хранилище. Для того, чтобы записать объект в хранилище мы должны поработать с хранилищем. За него отвечает класс &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.aspx" target="_blank"&gt;X509Store&lt;/a&gt;. Мы создадим этот объект с нуля и укажем какой именно контейнер в каком хранилище открывать. Для этого мы воспользуемся следующим конструктором: &lt;a href="http://msdn.microsoft.com/en-us/library/ms148581.aspx" target="_blank"&gt;X509Store Constructor (StoreName, StoreLocation)&lt;/a&gt;. Здесь я подробно останавливаться не буду, поскольку названия хранилищ и контейнеров мы уже рассматривали в одном из предыдущих постов: &lt;a href="http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx"&gt;Простой экспорт сертификатов в PowerShell&lt;/a&gt;, в этом посте все контейнеры показаны в первом снимке консоли. В нашем случае &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.storename.aspx" target="_blank"&gt;StoreName&lt;/a&gt; будет &lt;strong&gt;My&lt;/strong&gt; (&lt;em&gt;Personal&lt;/em&gt;), а &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.storelocation.aspx" target="_blank"&gt;Store Location&lt;/a&gt; будет &lt;strong&gt;CurrentUser&lt;/strong&gt; (контекст текущего пользователя):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$store&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.X509Store&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;My&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;CurrentUser&lt;/span&gt;&lt;span style="color: #800000"&gt;&amp;quot;&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Создали мы объект хранилища, теперь нам надо его открыть в режиме &lt;strong&gt;ReadWrite&lt;/strong&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Open([&lt;/span&gt;&lt;span style="color: #008080"&gt;System.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;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Этот флаг открытия хранилища указывать надо обязательно, иначе у вас просто не будет к нему доступа. Теперь когда хранилище открыто, можно методом &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509store.add.aspx" target="_blank"&gt;Add()&lt;/a&gt;, который в качестве аргумента принимает только x509Certificate2 объекты (он у нас уже есть в переменной $certs):&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #800080"&gt;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Close()&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; MSDN настоятельно рекомендует закрывать хранилище после того, как вы провели с ним необходимые операции.&lt;/p&gt;

&lt;p&gt;Вот и всё, собственно, у нас теперь PFX файл был успешно импортирован в хранилище.&lt;/p&gt;

&lt;p&gt;Когда вы импортируете сертификаты из &lt;strong&gt;p7b&lt;/strong&gt; (&lt;em&gt;PKCS#7&lt;/em&gt;) файла, то в нём может быть несколько сертификатов, поэтому здесь поменяется всего 2 строчки. Поскольку у нас в одном файле может быть несколько сертификатов, то для их чтения из файла будем использовать не x509Certificate2 объект, а специальный массив таких объектов – &lt;strong&gt;x509Certificate2Collection&lt;/strong&gt;, о котором мы уже говорили в предыдущем посте:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&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.IO.File&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;ReadAllBytes&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800080"&gt;$path&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&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.X509Certificate2Collection&lt;br /&gt;&lt;/span&gt;&lt;span style="color: #800080"&gt;$certs&lt;/span&gt;&lt;span style="color: #000000"&gt;.Import(&lt;/span&gt;&lt;span style="color: #800080"&gt;$bytes&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Мы сначала прочитали байтовый массив из файла и засунули его в коллекцию x509Certificate2 объектов. Т.к. сертификатов там несколько, а метод &lt;strong&gt;Add()&lt;/strong&gt; у x509Store за раз может взять только один объект – воспользуемся циклом:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$certs&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;$store&lt;/span&gt;&lt;span style="color: #000000"&gt;.Add(&lt;/span&gt;&lt;span style="color: #800080"&gt;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;)}&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;А в остальном схема импорта &lt;strong&gt;p7b&lt;/strong&gt; файлов будет такая же. Вот и всё, что я хотел рассказать по импорту сертификатов из файлов в хранилище. В принципе, используя эти знания вы уже можете затачивать код под свои нужды, тем более я везде, где это было необходимо, указывал ссылки на MSDN, где вы можете узнать более подробно этот материал. Но чтобы сделать жизнь чуточку проще, я постараюсь написать несколько полезных функций для управлениями сертификатами в PowerShell, что будет весьма актуально для Windows Server 2008 R2 Server Core.&lt;/p&gt;

&lt;p&gt;Спасибо за внимание &lt;img alt=":)" src="/smilies/happy.gif"&gt;&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=9932bca2-6f85-4ed5-b001-32a37b67b146"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,9932bca2-6f85-4ed5-b001-32a37b67b146.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=72d9376a-a668-4122-8a35-c27d9679e071</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=72d9376a-a668-4122-8a35-c27d9679e071</wfw:commentRss>
      <title>Сложный экспорт сертификатов в PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx</link>
      <pubDate>Mon, 07 Sep 2009 20:28:36 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;Продолжая тему экспорта сертификатов поговорим о более сложных вещах, чем простой экспорт сертификата из хранилища в CER/DER файл. На сей раз расскажу про экспорт сертификатов из хранилища в &lt;strong&gt;PFX&lt;/strong&gt; (&lt;em&gt;Personal Information Exchange Syntax Standard&lt;/em&gt;) и &lt;strong&gt;PKCS#7&lt;/strong&gt; (&lt;em&gt;Cryptographic Message Syntax Standard&lt;/em&gt;) формат. Будет немного треша, но в пределах разумного.&lt;/p&gt;  &lt;p&gt;Для экспорта сертификата в &lt;strong&gt;PFX&lt;/strong&gt; нам потребуется выполнить половину кода из предыдущей статьи: &lt;a href="http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx"&gt;Простой экспорт сертификатов в PowerShell&lt;/a&gt;.&lt;/p&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; &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;dir&lt;/span&gt;&lt;span style="color: #000000"&gt; cert:\currentuser)[4]&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Как вы помните, если экспортировать сертификат в PFX нам нужно указывать пароль:&lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Certificate Export Wizard windows" border="0" alt="Certificate Export Wizard windows" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PowerShell_1219B/exppfx.png" width="517" height="470" /&gt; &lt;/p&gt;

&lt;p&gt;Следовательно, конструктор метода &lt;a href="http://msdn.microsoft.com/en-us/library/dxz81eb9.aspx"&gt;Export(X509ContentType)&lt;/a&gt;, который мы использовали нам уже не подойдёт, поскольку в этот конструктор нельзя вложить пароль. Мы можем воспользоваться одним из оставшихся конструкторов:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms148397.aspx"&gt;Export(X509ContentType, SecureString)&lt;/a&gt; &lt;/li&gt;

  &lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/24ww6yzk.aspx"&gt;Export(X509ContentType, String)&lt;/a&gt; &lt;/li&gt;
&lt;/ul&gt;

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

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$password&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;Read-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;Password&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="font-style: italic; color: #5f9ea0"&gt;AsSecureString&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;А теперь по аналогии с примером из предыдущего поста укажем тип сертификата как PFX и применим наш метод &lt;a href="http://msdn.microsoft.com/en-us/library/ms148397.aspx"&gt;Export(X509ContentType, SecureString)&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$type&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.Security.Cryptography.X509Certificates.X509ContentType&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;Pfx&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;.Export(&lt;/span&gt;&lt;span style="color: #800080"&gt;$type&lt;/span&gt;&lt;span style="color: #000000"&gt;, &lt;/span&gt;&lt;span style="color: #800080"&gt;$password&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;У нас снова получится массив байтов, т.к. этот метод возвращает только его. Но что с этим бинарным мусором делать? Я сначала по наивности предположил, что его так же запаковать в &lt;strong&gt;Base64&lt;/strong&gt; и записать в файл. Да, у меня всё вышло хорошо, данные были записаны в файл и &lt;strong&gt;Certificate Import Wizard&lt;/strong&gt; принял его за валидный PFX файл. Но у меня всё обломалось на стадии ввода пароля, т.к. этот визард не хотел его брать. Ввиду отсутствия практики в этих делах, пришлось попросить помощи на одном из бложиков технета, откуда и пришёл ответ, что этот &lt;u&gt;Certificate Import Wizard не декодирует файл обратно из Base64&lt;/u&gt;, поэтому для записи в файл нужно писать сразу байты:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #000000"&gt;[&lt;/span&gt;&lt;span style="color: #008080"&gt;System.IO.File&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;WriteAllBytes&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800000"&gt;'&lt;/span&gt;&lt;span style="color: #800000"&gt;certificate.pfx&lt;/span&gt;&lt;span style="color: #800000"&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;/pre&gt;
&lt;/blockquote&gt;

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

&lt;p&gt;Но это всё относительно просто. Когда я задался вопросом “а как экспортировать в PKCS#7?”, то пришлось убить несколько часов на выяснение этого процесса. PKCS#7 удобен тем, что в себе может содержать кучу сертификатов и главным образом используется для хранения цепочки сертификатов (&lt;em&gt;Certificate Chain&lt;/em&gt;). Например, особенно наблюдательные пользователи при посещении многих HTTPS сайтов могут заметить, что поле AIA есть только у самих SSL сертификатов, а у промежуточных CA его уже нету. Но этих сертификатов нету и в хранилище сертификатов (Certificate Store). Напрашивается вопрос: а как же система построила эту цепочку сертификатов при отсутствующем AIA в сертификатах? Оказывается, всё очень просто, в RFC2246 есть хороший момент:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;font color="#804000"&gt;certificate_list 
      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; This is a sequence (chain) of X.509v3 certificates. The sender's 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; certificate must come first in the list. Each following 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; certificate must directly certify the one preceding it. Because 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; certificate validation requires that root keys be distributed 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; independently, the self-signed certificate which specifies the 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; root certificate authority may optionally be omitted from the 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; chain, under the assumption that the remote end must already 

      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; possess it in order to validate it in any case.&lt;/font&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Это означает, что веб-сервер может вместе с SSL сертификатом отправлять клиенту и цепочку сертификатов, которая как раз и есть в формате PKCS#7. Если что, это было просто введение к назначению данного типа сертификатов.&lt;/p&gt;

&lt;p&gt;Предупреждаю сразу, что методы &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.export.aspx"&gt;x509Certificate2.Export Method&lt;/a&gt; нам не сгодятся, т.к. в описании метода есть ремарка:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;The contentType parameter accepts only the following values of the &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.aspx"&gt;&lt;em&gt;X509ContentType&lt;/em&gt;&lt;/a&gt;&lt;em&gt; enumeration: &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.cert.aspx"&gt;&lt;em&gt;Cert&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.serializedcert.aspx"&gt;&lt;em&gt;SerializedCert&lt;/em&gt;&lt;/a&gt;&lt;em&gt;, and &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.pkcs12.aspx"&gt;&lt;em&gt;Pkcs12&lt;/em&gt;&lt;/a&gt;&lt;em&gt;. Passing any other value causes a &lt;/em&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.cryptographicexception.aspx"&gt;&lt;em&gt;CryptographicException&lt;/em&gt;&lt;/a&gt;&lt;em&gt; to be thrown.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Хоть класс System.Security.Cryptography.X509Certificates.X509ContentType и имеет в себе атрибут PKCS7, но метод Export класса x509Certificate2 его просто не принимает. Это был провал! Но делать нечего, пришлось искать. Наткнулся я вот на один замечательный пост: &lt;a href="http://blogs.technet.com/vishalagarwal/archive/2009/04/30/pkcs7-p7b-bag-of-certificates-and-powershell.aspx"&gt;PKCS7 (p7b) bag of certificates and powershell&lt;/a&gt;. Но там пример как раз наоборот – как извлечь сертификаты из p7b файла и вывести их в виде x509Certificate2 объектов:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #000000"&gt;[&lt;/span&gt;&lt;span style="color: #008080"&gt;reflection.assembly&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;LoadWithPartialName&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;System.Security&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;$data&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.IO.File&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;ReadAllBytes&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;certificates.p7b&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;$cms&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.pkcs.signedcms&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$cms&lt;/span&gt;&lt;span style="color: #000000"&gt;.Decode(&lt;/span&gt;&lt;span style="color: #800080"&gt;$data&lt;/span&gt;&lt;span style="color: #000000"&gt;)
&lt;/span&gt;&lt;span style="color: #800080"&gt;$cms&lt;/span&gt;&lt;span style="color: #000000"&gt;.Certificates | &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;foreach&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;$_&lt;/span&gt;&lt;span style="color: #000000"&gt;} | &lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;echo&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Автор поста вообще удивительный человек. Просто взял и выложил код без каких-либо комментариев, предполагая, что все знают что делает этот код в деталях. Попробую за него сделать это я. Данный код читает бинарный мусор из файла (обратите внимание, что используется обратная операция экспорта PFX бинарного массива в файл). Далее создаётся объект &lt;strong&gt;CMS&lt;/strong&gt; (&lt;em&gt;Cryptographic Message Syntax&lt;/em&gt;). И что мы с него имеем:&lt;/p&gt;

&lt;div style="width: 915px"&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] [void][reflection.assembly]::LoadWithPartialName(&amp;quot;System.Security&amp;quot;)
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cms = new-object system.security.cryptography.pkcs.signedcms
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cms


Version      : 0
ContentInfo  : System.Security.Cryptography.Pkcs.ContentInfo
Detached     : False
Certificates : {}
SignerInfos  : {}



&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cms | gm -MemberType methods


   TypeName: System.Security.Cryptography.Pkcs.SignedCms

Name             MemberType Definition
----             ---------- ----------
CheckHash        Method     System.Void CheckHash()
CheckSignature   Method     System.Void CheckSignature(bool verifySignatureOnly), System.Void CheckSignature(System....
ComputeSignature Method     System.Void ComputeSignature(), System.Void ComputeSignature(System.Security.Cryptograph...
Decode           Method     System.Void Decode(byte[] encodedMessage)
Encode           Method     byte[] Encode()
Equals           Method     bool Equals(System.Object obj)
GetHashCode      Method     int GetHashCode()
GetType          Method     type GetType()
RemoveSignature  Method     System.Void RemoveSignature(int index), System.Void RemoveSignature(System.Security.Cryp...
ToString         Method     string ToString()


&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;Мы имеем объект с 5 свойствами и различными методами. В коде используется метод &lt;strong&gt;Decode()&lt;/strong&gt; и как видно в описании метода, в качестве аргумента принимается массив байтов, полученный из p7b файла. Этот метод преобразует этот массив обратно в массив объектов x509Certificate2, что видно из последней строки кода. Более-менее тут что-то понятно. Следовательно, для экспорта нам нужно проделать операцию наоборот, создать объект CMS, в свойство Certificates запихать x509Certificate2 объекты сертификатов и применить метод &lt;strong&gt;Encode()&lt;/strong&gt;. Чтобы использовать этот метод у нас в свойстве Certificates должны храниться x509Certificate2 объекты наших сертификатов, которые хотим экспортировать. Но тут меня ждал облом, т.к. свойство &lt;strong&gt;Certificates&lt;/strong&gt; является Read-only и записать туда ничего нельзя. Однако, PowerTab мне показал, что там есть что-то интересное:&lt;/p&gt;

&lt;div style="width: 915px"&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] $cms.Certificates.
                                ╔═ $cms.Certificates. ═════════════╗
                                ║&lt;span style="background-color: #ff0000"&gt;&lt;font color="#000000"&gt; $cms.Certificates.PSBase&lt;/font&gt;         &lt;/span&gt;║
                                ║ $cms.Certificates.Add(           ║
                                ║ $cms.Certificates.AddRange(      ║
                                ║ $cms.Certificates.Clear(         ║
                                ║ $cms.Certificates.Contains(      ║
                                ║ $cms.Certificates.CopyTo(        ║
                                ║ $cms.Certificates.Equals(        ║
                                ║ $cms.Certificates.Export(        ║
                                ║ $cms.Certificates.Find(          ║
                                ║ $cms.Certificates.GetEnumerator( ║
                                ║ $cms.Certificates.GetHashCode(   ║
                                ║ $cms.Certificates.GetType(       ║
                                ║ $cms.Certificates.Import(        ║
                                ║ $cms.Certificates.IndexOf(       ║
                                ║ $cms.Certificates.Insert(        ║
                                ║ $cms.Certificates.Remove(        ║
                                ║ $cms.Certificates.RemoveAt(      ║
                                ║ $cms.Certificates.RemoveRange(   ║
                                ║ $cms.Certificates.ToString(      ║
                                ║ $cms.Certificates.Item(          ║
                                ║ $cms.Certificates.Capacity       ║
                                ║ $cms.Certificates.Count          ║
                                ╚═[1] 1-22 (22/22)]════════════════╝&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Я испробовал несколько по смыслу похожих методов, как &lt;strong&gt;Add&lt;/strong&gt;, &lt;strong&gt;AddRange&lt;/strong&gt; и &lt;strong&gt;Import&lt;/strong&gt;, но всё неудачно. Сертификаты никак не хотели туда помещаться. После некоторого времени возни я бросил это занятие, как бесполезное, т.к. там ловить нечего:&lt;/p&gt;

&lt;div style="width: 915px"&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] $cms.Certificates | gm
&lt;font color="#ff0000"&gt;Get-Member : No object has been specified to the get-member cmdlet.
At line:1 char:23
+ $cms.Certificates | gm &amp;lt;&amp;lt;&amp;lt;&amp;lt;
    + CategoryInfo          : CloseError: (:) [Get-Member], InvalidOperationException
    + FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand&lt;/font&gt;

&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;Вобщем, всякие вариации с этим CMS объектов никаких успехов не приносили до тех пор, пока я не посмотрел тип этого свойства Certificates:&lt;/p&gt;

&lt;div style="width: 915px"&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] $cms.Certificates.GetType().FullName
System.Security.Cryptography.X509Certificates.X509Certificate2Collection&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Я отправился на MSDN читать макулатуру по этому классу (точнее по его членам): &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2collection_members.aspx" target="_blank"&gt;X509Certificate2Collection Members&lt;/a&gt;. Если вы ещё не забыли, то мы ищем способ разобрать наш x509Certificate2 объект на массив байтов, который бы соответствовал формату PKCS#7. Здесь из годных методов я нашёл метод &lt;a href="http://msdn.microsoft.com/en-us/library/ms148480.aspx"&gt;Add(X509Certificate2)&lt;/a&gt;. У меня уже есть этот объект, поэтому мы его можем добавить в объект &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2collection.aspx" target="_blank"&gt;X509Certificate2Collection&lt;/a&gt;. Данный класс по сути представляет массив объектов x509Certificate2. Давайте сделаем:&lt;/p&gt;

&lt;div style="width: 915px"&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 = (dir cert:\currentuser\my)[4]
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cert1 = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cert1.Add($cert)
0
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $cert1

Thumbprint                                Subject
----------                                -------
0F5157A8342C66493E7B1354530DD7A9F980BC69  CN=vPodans


&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;ну хорошо, преобразовали мы x509Certificate2 в X509Certificate2Collection, а что дальше? Нам по прежнему нужен этот дурацкий массив байтов. После этого я посмотрел на метод &lt;a href="http://msdn.microsoft.com/en-us/library/ms148490.aspx" target="_blank"&gt;X509Certificate2Collection Export Method (X509ContentType)&lt;/a&gt; нового класса и прочитал ремарки:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;p&gt;&lt;em&gt;This method supports content types that do not require a password.&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Вот тут я и сказал “слава &lt;strike&gt;сиськам&lt;/strike&gt;Протоколу!”. Данный метод позволяет экспортировать объекты сертификатов в любой тип, который не требует пароля (т.е. всё, кроме PFX/PKCS#12). А дальше уже по отработанной схеме:&lt;/p&gt;

&lt;div style="width: 915px"&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] $type = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs7
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $bytes = $cert1.Export($type)
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] [System.IO.File]::WriteAllBytes('certificate.p7b', $bytes)
&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;Вот таким долгим и тяжёлым (для меня, во всяком случае) я смог его победить и научиться экспортировать сертификаты в PKCS#7.&lt;/p&gt;

&lt;p&gt;Что нас ждёт дальше? А дальше, возможно, поговорим про SerializedCert и SerializedStore (а может и не будем говорить) и уже импорт сертификатов из файлов в Certificate Store. А на сегодня, пожалуй, хватит.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=72d9376a-a668-4122-8a35-c27d9679e071"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,72d9376a-a668-4122-8a35-c27d9679e071.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
    </item>
    <item>
      <trackback:ping>http://www.sysadmins.lv/Trackback.aspx?guid=972e7000-555d-40af-9561-18d70467d82a</trackback:ping>
      <pingback:server>http://www.sysadmins.lv/pingback.aspx</pingback:server>
      <pingback:target>http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx</pingback:target>
      <dc:creator>Camelot</dc:creator>
      <wfw:comment>http://www.sysadmins.lv/CommentView,guid,972e7000-555d-40af-9561-18d70467d82a.aspx</wfw:comment>
      <wfw:commentRss>http://www.sysadmins.lv/SyndicationService.asmx/GetEntryCommentsRss?guid=972e7000-555d-40af-9561-18d70467d82a</wfw:commentRss>
      <title>Простой экспорт сертификатов в PowerShell</title>
      <guid isPermaLink="false">http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx</guid>
      <link>http://www.sysadmins.lv/PermaLink,guid,972e7000-555d-40af-9561-18d70467d82a.aspx</link>
      <pubDate>Sun, 06 Sep 2009 09:46:46 GMT</pubDate>
      <description>&lt;div&gt;&lt;p&gt;С различной периодичностью на ньюсгруппах и англоязычных форумах встречаю вопрос, как экспортировать сертификаты из хранилища (Certificate Store) или сертификаты цифровых подписей файлов в .CER или .DER файл. Сегодня я продемонстрирую простой метод для экспорта этих сертификатов.&lt;/p&gt;  &lt;p&gt;На самом деле разница между экспортом сертификата из хранилища сертификатов и подписанного файла заключается только в методе извлечения самого сертификата в &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx" target="_blank"&gt;x509Certificate2&lt;/a&gt; объект. Давайте начнём с самого простого – экспорт сертификата из хранилища. В PowerShell уже есть свой провайдер для этого хранилища и свой PSDrive:&lt;/p&gt;  &lt;div style="width: 915px"&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] dir cert:\


Location   : CurrentUser
StoreNames : {SmartCardRoot, UserDS, AuthRoot, CA...}

Location   : LocalMachine
StoreNames : {SmartCardRoot, AuthRoot, CA, Trust...}



&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] dir cert:\currentuser


Name : SmartCardRoot

Name : UserDS

Name : AuthRoot

Name : CA

Name : AddressBook

Name : Trust

Name : Disallowed

Name : My

Name : Root

Name : TrustedPeople

Name : TrustedPublisher

Name : REQUEST



&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] dir cert:\currentuser\my


    Directory: Microsoft.PowerShell.Security\Certificate::currentuser\my


Thumbprint                                Subject
----------                                -------
9C5E4DCEF6598C1298894F62D4BD16E601B8C780  CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=W...
986D375362652FE9E39BA4D042A6B8BA75745998  CN=Administrator, CN=Users, DC=sysadmins, DC=lv
4BB89D732920DD91DE66983DDF2CC4EEC272A802  CN=Administrator, CN=Users, DC=sysadmins, DC=lv
14B931DB4790403CCE2A3D03B62638FC7A0D5F34  CN=Administrator, OU=Administrators, DC=sysadmins, DC=lv


&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;Если просто посмотреть содержимое Cert:\, то мы увидим там 2 хранилища&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;strong&gt;CurrentUser&lt;/strong&gt; – представляет хранилище текущего пользователя, т.е. является аналогом графической консоли CertMgr.msc &lt;/li&gt;

  &lt;li&gt;&lt;strong&gt;LocalMachine&lt;/strong&gt; – представляет хранилище локального компьютера и является аналогом графической консоли MMC – Certificates, запущенной в контексте LocalComputer. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Внутри уже видны контейнеры, которые мы видим в виде папок в MMC консоли. А дальше уже хранятся наши сертификаты. Эти сертификаты здесь представлены в виде массива &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.aspx" target="_blank"&gt;x509Certificate2&lt;/a&gt;.&lt;/p&gt;

&lt;div style="width: 915px"&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] (dir cert:\currentuser\my)[0].gettype().FullName
System.Security.Cryptography.X509Certificates.X509Certificate2
&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;Если посмотреть свойства этого объекта через Get-Member, то мы сможем там увидеть метод &lt;strong&gt;Export()&lt;/strong&gt;. Но лучше посмотреть этот метод на MSDN, т.к. он имеет несколько конструкторов: &lt;a href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509certificate2.export.aspx" target="_blank"&gt;x509Certificate2.Export Method&lt;/a&gt;. Из них нас заинтересует только первый конструктор, который &lt;a href="http://msdn.microsoft.com/en-us/library/dxz81eb9.aspx"&gt;Export(X509ContentType)&lt;/a&gt;. Остальные 2 необходимы для экспорта с паролем (только для PFX). Но, как мы видим из описания метода, нам надо ещё указать &lt;strong&gt;x509ContentType&lt;/strong&gt; объект, который будет указывать нам на тип экспортируемого сертификата. Типы экспортируемых сертификатов можно посмотреть по ссылке: &lt;a title="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.aspx" href="http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.aspx"&gt;http://msdn.microsoft.com/en-us/library/system.security.cryptography.x509certificates.x509contenttype.aspx&lt;/a&gt; или в консоли PowerShell:&lt;/p&gt;

&lt;div style="width: 915px"&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] [System.Enum]::GetNames([system.security.cryptography.x509certificates.x509contenttype])
Unknown
Cert
SerializedCert
Pfx
Pkcs12
SerializedStore
Pkcs7
Authenticode&lt;/p&gt;&lt;/span&gt;&lt;/font&gt;&lt;/pre&gt;
  &lt;/blockquote&gt;
&lt;/div&gt;

&lt;p&gt;Нас сейчас будет интересовать только тип &lt;strong&gt;Cert&lt;/strong&gt; (только открытая часть сертификата).&lt;/p&gt;

&lt;p&gt;Теперь мы уже знаем достаточно много, чтобы уже начать писать код. Мы сейчас получим объект сертификата, укажем тип экспортируемого сертификата и выполним метод Export():&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;dir&lt;/span&gt;&lt;span style="color: #000000"&gt; cert:\&lt;/span&gt;&lt;span style="color: #800000"&gt;currentuser\My&lt;/span&gt;&lt;span style="color: #000000"&gt;)[0]
&lt;/span&gt;&lt;span style="color: #800080"&gt;$type&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.Security.Cryptography.X509Certificates.X509ContentType&lt;/span&gt;&lt;span style="color: #000000"&gt;]::&lt;/span&gt;&lt;span style="color: #8b4513"&gt;Cert&lt;/span&gt;&lt;span style="color: #000000"&gt;
&lt;/span&gt;&lt;span style="color: #800080"&gt;$ExportedData&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;.Export(&lt;/span&gt;&lt;span style="color: #800080"&gt;$type&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;Но это ещё не всё. Посмотрите, что у вас находится в переменной &lt;strong&gt;$ExportedData&lt;/strong&gt;! Там на самом деле огромный массив байтов (в среднем более 2-20 тысяч элементов). Это же и указано в описании метода, что он возвращает. Именно массив байтов. Но что с ним делать? Я сам по-началу думал об этом, пока не вспомнил про одну вещь:&lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Certificate Export Wizard" border="0" alt="Certificate Export Wizard" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PowerShell_8E9B/certexportb64_1.png" width="517" height="470" /&gt; &lt;/p&gt;

&lt;p&gt;У нас есть выбор, как экспортировать сертификат – в DER или Base64 кодировке. Когда я писал про &lt;a href="http://www.sysadmins.lv/PermaLink,guid,29898a6c-aceb-4738-82d8-318bc89272cc.aspx" target="_blank"&gt;PsFCIV&lt;/a&gt;, то у меня была такая же ситуация. Hasher у меня так же возвращал массив байтов, который мы сразу же загоняли в Base64 кодировку. В нашем случае потребуется то же самое:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$base64Data&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;ToBase64String&lt;/span&gt;&lt;span style="color: #000000"&gt;(&lt;/span&gt;&lt;span style="color: #800080"&gt;$ExportedData&lt;/span&gt;&lt;span style="color: #000000"&gt;)&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;И на выходе мы молучим длинную Base64 строку, которую уже и нужно экспортировать в файл любым удобным для вас методом:&lt;/p&gt;

&lt;blockquote&gt;
  &lt;pre&gt;&lt;span style="color: #800080"&gt;$base64Data&lt;/span&gt;&lt;span style="color: #000000"&gt; &amp;gt; path\file.cer
&lt;/span&gt;&lt;span style="color: #5f9ea0; font-weight: bold"&gt;Set-Content&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Path&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800000"&gt;path\file&lt;/span&gt;&lt;span style="color: #000000"&gt;.cer &lt;/span&gt;&lt;span style="font-style: italic; color: #5f9ea0"&gt;-Value&lt;/span&gt;&lt;span style="color: #000000"&gt; &lt;/span&gt;&lt;span style="color: #800080"&gt;$base64Data&lt;/span&gt;&lt;/pre&gt;
&lt;/blockquote&gt;

&lt;p&gt;вы можете убедиться в этом просто открыв .CER файл.&amp;#160; Чтобы получить объект сертификата из цифровой подписи файла, то мы можем просто воспользоваться командлетом &lt;strong&gt;Get-AuthenticodeSignature&lt;/strong&gt; и выбрать свойство &lt;strong&gt;SignerCertificate&lt;/strong&gt;. Если подпись файла дополнительно подписана сертификатом сервера времени, то вы можете использовать так же и свойство &lt;strong&gt;TimeStampCertificate&lt;/strong&gt;:&lt;/p&gt;

&lt;div style="width: 915px"&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] $a.SignerCertificate

Thumbprint                                Subject
----------                                -------
9E95C625D81B2BA9C72FD70275C3699613AF61E3  CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=W...


&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $a = Get-AuthenticodeSignature .\Desktop\EASetup.exe
&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $a.SignerCertificate

Thumbprint                                Subject
----------                                -------
9E95C625D81B2BA9C72FD70275C3699613AF61E3  CN=Microsoft Corporation, OU=MOPR, O=Microsoft Corporation, L=Redmond, S=W...


&lt;font color="#ff0000"&gt;[↓]&lt;/font&gt; [vPodans] $a.TimeStamperCertificate

Thumbprint                                Subject
----------                                -------
4D6F357F0E6434DA97B1AFC540FB6FDD0E85A89F  CN=Microsoft Time-Stamp Service, OU=nCipher DSE ESN:85D3-305C-5BCF, OU=MOP...


&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/system.security.cryptography.x509certificates.x509certificate2.aspx" target="_blank"&gt;x509Certificate2&lt;/a&gt; и дальше их можно экспортировать тем же самым путём, как мы это делали для сертификатов из Certificate Store. Собственно, для извлечения сертификатов из цифровых подписей файлов я написал неплохой скриптик, который добавляет в контекстное меню элемент &lt;strong&gt;Export Certificate&lt;/strong&gt;:&lt;/p&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Export Certificate Context menu" border="0" alt="Export Certificate Context menu" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PowerShell_8E9B/certcontmenu_3.png" width="290" height="54" /&gt; &lt;/p&gt;

&lt;p&gt;и по нажатию на него цифровая подпись будет экспортирована в &lt;font color="#0000ff"&gt;MyDocs\FileName.ext.cer&lt;/font&gt;, где &lt;font color="#0000ff"&gt;FileName.ext&lt;/font&gt; – оригинальное имя файла и к нему просто пристыковывается расширение CER. В скрипте предусмотрены несколько диалоговых окон о состоянии сертификата:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;файл подписан и хеш файла соответствует хешу в цифровой подписи: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Valid Certificate" border="0" alt="Valid Certificate" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PowerShell_8E9B/validcertmsg.png" width="386" height="148" /&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;файл подписан, но хеш файла не соответствует хешу в цифровой подписи: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="Hash Mismatch" border="0" alt="Hash Mismatch" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PowerShell_8E9B/hmmsg_1.png" width="490" height="208" /&gt; &lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;файл не содержит цифровых подписей: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;img style="border-right-width: 0px; display: block; float: none; border-top-width: 0px; border-bottom-width: 0px; margin-left: auto; border-left-width: 0px; margin-right: auto" title="No certificate" border="0" alt="No certificate" src="http://www.sysadmins.lv/content/binary/WindowsLiveWriter/PowerShell_8E9B/nsmsg.png" width="491" height="178" /&gt; &lt;/p&gt;

&lt;p&gt;В двух последних случаях сертификат не экспортируется никуда по очевидным причинам. И, собственно скрипты-инсталляторы этого контекстного меню с рабочим кодом для:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;PowerShell 1.0: &lt;/li&gt;
&lt;/ul&gt;

&lt;div&gt;
  &lt;p style="border-bottom: silver 1px solid; position: relative; border-left: silver 1px solid; width: 245px; 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/ExportCertificate_ps1.0.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/ExportCertificate_ps1.0.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/ExportCertificate_ps1.0.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;8,97 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/ExportCertificate_ps1.0.ps1" target="_self" alt="Download File"&gt;ExportCertificate_ps1.0.ps1&lt;/a&gt; &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;ul&gt;
  &lt;li&gt;PowerShell V2: &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;/p&gt;

&lt;div&gt;
  &lt;p style="border-bottom: silver 1px solid; position: relative; border-left: silver 1px solid; width: 245px; 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/ExportCertificate_ps2.0.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/ExportCertificate_ps2.0.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/ExportCertificate_ps2.0.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;8,34 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/ExportCertificate_ps2.0.ps1" target="_self" alt="Download File"&gt;ExportCertificate_ps2.0.ps1&lt;/a&gt; &lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;

&lt;p&gt;В следующих статьях я планирую поговорить про импорт сертификатов в Certificate Store, а так же и экспорт сертификатов с закрытыми ключами в PFX файл с использованем Windows PowerShell.&lt;/p&gt;&lt;img width="0" height="0" src="http://www.sysadmins.lv/aggbug.ashx?id=972e7000-555d-40af-9561-18d70467d82a"/&gt;&lt;br/&gt;&lt;hr/&gt;PowerShell Powered - http://www.sysadmins.lv&lt;/div&gt;</description>
      <comments>http://www.sysadmins.lv/CommentView,guid,972e7000-555d-40af-9561-18d70467d82a.aspx</comments>
      <category>PowerShell</category>
      <category>PowerShell / Certificates</category>
    </item>
  </channel>
</rss>