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?», то скорее всего придётся вручную добавлять сертификат в Доверенные издатели.

Сообщение о том, что скрипт был изменён

Подписал скрипт и запускаю, но получаю такую ошибку:

Script_name.ps1 might have been changed by an unauthorized user or process, because the hash of the file does not match the hash stored in the digital signature. The script cannot run on the specified system.

Какой-то глюк, т.к. на следующий день, подписал это скрипт ещё раз и всё заработало.
На всякий случай, после подписания скрипта можно проверить:

Get-AuthenticodeSignature .\Script_name.ps1 | Format-List Status, StatusMessage
Status        : Valid
StatusMessage : Signature verified.


Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *