Contents of this directory is archived and no longer updated.

В предыдущих статьях мы с вами уже изучили методы экспорта сертификатов из хранилища Certificate Store в файл:

а так же рассмотрели сопутствующие вопросы. Теперь же предлагаю рассмотреть обратную операцию – добавление сертификатов в cert store из файлов. Этот процесс будет несколько легче, чем экспорт, поэтому я в одном посте покажу импорт всех типов сертификатов (они все используют одну схему).

Для импорта нам потребуется метод x509Certificate.Import(), который так же как и метод Export() имеет несколько конструкторов. Мы можем выбрать один универсальный, который подойдёт нам для всех типов файлов сертификатов и это будет конструктор: X509Certificate2.Import Method (String, SecureString, X509KeyStorageFlags). В качестве аргументов он принимает следующее:

  • String – путь к файлу сертификата
  • SecureString – строка с паролем. Требуется только для импорта PFX сертификатов, т.к. остальные типы файлов не содержат закрытых ключей и защищать их паролем нет смысла. Если это не PFX, то значение этого аргумента просто выставляется в $null.
  • объект типа X509KeyStorageFlags, который описывает область хранения сертификатов.

Давайте немного разберёмся с флагами последнего аргумента:

  • DefaultKeySet – указывает, что сертификат предназначен для импорта в контейнер Personal хранилища CurrentUser (дефолт).
  • Exportable – используется только для PFX файлов и говорит, будет ли возможность экспортировать сертификат с закрытым ключом. Если мы этот флаг не указываем, то после импорта не будет возможности снова экспортировать в PFX файл.
  • MachineKeySet – указывает, что сертификат будет установлен в хранилище компьютера (LocalSystem).
  • PersistKeySet – используется только для PFX и сохраняет пароль от PFX файла в сертификате. Данный пароль будет использован при дальнейшем экспорте в PFX файл (будет работать только с флагом Exportable).
  • UserKeySet – указывает, что сертификат будет установлен в пользовательское хранилище.
  • UserProtected – используется только для PFX файлов и для пользовательских сертификатов. Этот флаг включает Private Key Strong Protection, который при каждом использовании закрытого ключа будет требовать ввода пароля.

Примечание: вы никогда не должны использовать флаг UserProtected для компьютерных сертификатов, поскольку они используются в контексте LocalSystem и у вас просто не будет возможности ввести пароль для использования этого закрытого ключа.

Т.к. X509KeyStorageFlags на самом деле является перечислителем (enumerator), то создавать его объект не обязательно и флаги можно просто использовать как строки. PowerShell уже сам подобъёт эти флаги к нужному типу данных.

т.к. у нас ещё нет готового объекта сертификатов, то мы его просто создаём:

$certs = New-Object system.security.cryptography.x509certificates.x509certificate2

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

$path = "mycert.pfx"
$password = Read-Host "Type password for PFX certificate" -AsSecureString
$flags = "UserKeySet, Exportable"
$certs.Import($path, $password, $flags)

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

[↓] [vPodans] $certs = New-Object system.security.cryptography.x509certificates.x509certificate2
[↓] [vPodans] $path = "mycert.pfx"
[↓] [vPodans] $password = Read-Host "Type password for PFX certificate" -AsSecureString
Type password for PFX certificate: *
[↓] [vPodans] $flags = "UserKeySet, Exportable"
[↓] [vPodans] $certs.Import($path, $password, $flags)
[↓] [vPodans] $certs

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


[↓] [vPodans]

как видите, у нас всё случилось, PFX файл был успешно прочитан и помещён в объект x509Certificate2. Но это только половина дела, поскольку этот сертификат пока существует только самом в объекте, но не в хранилище. Для того, чтобы записать объект в хранилище мы должны поработать с хранилищем. За него отвечает класс X509Store. Мы создадим этот объект с нуля и укажем какой именно контейнер в каком хранилище открывать. Для этого мы воспользуемся следующим конструктором: X509Store Constructor (StoreName, StoreLocation). Здесь я подробно останавливаться не буду, поскольку названия хранилищ и контейнеров мы уже рассматривали в одном из предыдущих постов: Простой экспорт сертификатов в PowerShell, в этом посте все контейнеры показаны в первом снимке консоли. В нашем случае StoreName будет My (Personal), а Store Location будет CurrentUser (контекст текущего пользователя):

$store = New-Object system.security.cryptography.X509Certificates.X509Store "My", "CurrentUser"

Создали мы объект хранилища, теперь нам надо его открыть в режиме ReadWrite:

$store.Open([System.Security.Cryptography.X509Certificates.OpenFlags]::ReadWrite)

Этот флаг открытия хранилища указывать надо обязательно, иначе у вас просто не будет к нему доступа. Теперь когда хранилище открыто, можно методом Add(), который в качестве аргумента принимает только x509Certificate2 объекты (он у нас уже есть в переменной $certs):

$store.Add($certs)
$store.Close()

Примечание: MSDN настоятельно рекомендует закрывать хранилище после того, как вы провели с ним необходимые операции.

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

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

$bytes = [System.IO.File]::ReadAllBytes($path)
$certs = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection$certs.Import($bytes)

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

$certs | %{$store.Add($_)}

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

Спасибо за внимание :-)


Share this article:

Comments:

Comments are closed.