Архив рубрики: Software

Windows: Создать сертификат и подписать PowerShell скрипт

В этой заметке я описал шаги по созданию сертификата и подписи PowerShell скрипта с помощью этого сертификата. Сегодня у меня истёк срок действия старого сертификата и я попытался найти эту инструкцию, но не дочитал до того момента, где описан новый способ. Вот в этой заметке я решил всё описать с самого начала.

Открываем PowerShell с правами админа.

 

1. Создаём переменную с названием сертификата (по этому названию мы будем искать сертификат и обращаться к нему):

Administrator: Windows PowerShell
$certname = "PowerShell User"

2. Создадим сертификат, используя название из этой переменной:

Administrator: Windows PowerShell
$authenticode = New-SelfSignedCertificate -Subject $certname -NotAfter (Get-Date).AddMonths(24) -CertStoreLocation Cert:\CurrentUser\My -Type CodeSigningCert
Здесь я создал сертификат сроком на 2 года (24 месяца). По умолчанию сертификат создаётся сроком только на один год.

 

3. Проверим, получилось ли создать:

Administrator: Windows PowerShell
$authenticode

   PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

Thumbprint                                Subject
----------                                -------
7F99AFA142CF981F48B44E353FB06C4B36496AEC  CN=PowerShell User
Сертификат создан в личном хранилище текущего пользователя. Если вы работаете под обычным пользователем, а консоль была запущена от имени админа (другого пользователя), то следующий шаг также выполняем под админом!

 

4. Запускаем консоль Средство диспетчера сертификатов:

Administrator: Windows PowerShell
certmgr.msc

5. Находим наш сертификат:

Certificates - Current User\Personal\Certificates\PowerShell User
Если консоль была открыта и сертификат не видно, обновите список (ПКМ-Rerfresh)

 

6. Экспортируем его:
ActionAll TasksExport…NextYes, export the private keyNextPersonal Information Exchange — PKCS #12 (.PFX)Next
7. Задаём пароль для защиты закрытого ключа, затем выбираем место сохранения.

В принципе можно и через консоль экспортировать сертификат в нужном формате, но это не очень удобно, причём нужно отдельной переменной указывать пароль.

 

8. После того, как сертификат сохранён в файл, делаем на этом файле двойной щелчок мыши и импортируем сертификат на локальную машину
9. При импортировании указываем в качестве хранилища Trusted Root Certification Authorities.
10. Повторяем п.8, но на этот раз указываем в качестве хранилища Trusted Publishers.
11. Теперь можно подписать файл со скриптом:

$cert = Get-ChildItem -Path Cert:\LocalMachine\root | Where-Object Subject -EQ "CN=PowerShell User"
Set-AuthenticodeSignature -FilePath .\SignScript.ps1 -Certificate $cert

Directory: X:\Users\Denis\Documents\PSUtils
SignerCertificate                         Status                                 Path
-----------------                         ------                                 ----
BC630C88DF6689B0CAE153443FBA1484DB91892C  Valid                                  SignScript.ps1

Возможные ошибки

Если при экспортировании на автопилоте ткнуть кнопку «Далее» и экспортировать сертификат как «DER encoded binary X.509 (.CER)», то при попытки подписать скрипт можно получить такую ошибку:

Set-AuthenticodeSignature -FilePath .\SignScript.ps1 -Certificate $cert
Set-AuthenticodeSignature : Cannot sign code. The specified certificate is not suitable for code signing.
At line:1 char:1
+ Set-AuthenticodeSignature -FilePath .\SignScript.ps1 -Certificate $ce ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (:) [Set-AuthenticodeSignature], PSArgumentException
    + FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.SetAuthenticodeSignatureCommand
Нам нужен файл сертификата именно в формате .PFX. Так что повторяем шаги заново, особенно повнимательнее п.6.

 

В хранилище сертификатов можно попасть из консоли. Например отобразить список сертификатов в хранилище для текущего пользователя и удалить их:

cd Cert:\CurrentUser\My
PS Cert:\CurrentUser\My> ls
 PSParentPath: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

Thumbprint                                Subject
----------                                -------
FDF7BD22D34CD65C866A3D75ACC6983FB8B6FCF5  CN=PowerShell User
FB8E4E49F3BA0C738D131232CF66E117F0CDB7A7  CN=localhost
F6826828D64B7AE3EC35BBD5543BBEC45050B01D  CN=PowerShell User
C4947C76A2A29A6586FDC8BA85B07882866665F8  CN=PowerShell User
BC8844E72DE7CB300FDA188D48E5915E350C3190  CN=PowerShell User
AE58F79184744B959A522E3D94F9C0F77F582ACC  CN=PowerShell User
PS Cert:\CurrentUser\My> rm .\AE58F79184744B959A522E3D94F9C0F77F582ACC
PS Cert:\CurrentUser\My> rm .\BC8844E72DE7CB300FDA188D48E5915E350C3190
PS Cert:\CurrentUser\My> rm .\C4947C76A2A29A6586FDC8BA85B07882866665F8
PS Cert:\CurrentUser\My> rm .\F6826828D64B7AE3EC35BBD5543BBEC45050B01D

Если при запуске скрипта появляется запрос «Do you want to run software from this untrusted publisher?», то скорее всего придётся вручную добавлять сертификат в Доверенные издатели.