Signtool позволяет мне подписать код, но Set-AuthenticodeSignature говорит, что "сертификат не подходит для подписи кода"
У меня есть самоподписанный сертификат подписи кода (сделанный с указаниями этого ответа), и он отлично работает, когда я использую signtool.exe
. Но если я попытаюсь подписать его с помощью Powershell, это не сработает.
Подписание с помощью значка
C:\>signtool sign /v /n "VetWeb" SetupRDPPermissions.ps1
The following certificate was selected:
Issued to: VetWeb
Issued by: VetWeb CA
Expires: Sat Dec 31 18:59:59 2039
SHA1 hash: 84136EBF8D2603C2CD6668C955F920C6C6482EE4
Done Adding Additional Store
Successfully signed: SetupRDPPermissions.ps1
Number of files successfully Signed: 1
Number of warnings: 0
Подписание в Powershell
PS C:\> $cert = @(Get-Childitem cert:\CurrentUser\My | Where-Object -FilterScript {$_.Subject -eq 'CN=VetWeb'})[0]
PS C:\> Set-AuthenticodeSignature SetupRDPPermissions.ps1 $cert
Set-AuthenticodeSignature : Cannot sign code. The specified certificate is not suitable for code signing.
At line:1 char:26
+ Set-AuthenticodeSignature <<<< SetupRDPPermissions.ps1 $cert
+ CategoryInfo : InvalidArgument: (:) [Set-AuthenticodeSignature], PSArgumentException
+ FullyQualifiedErrorId : Argument,Microsoft.PowerShell.Commands.SetAuthenticodeSignatureCommand
PS C:\> $cert | format-list *
PSPath : Microsoft.PowerShell.Security\Certificate::CurrentUser\My\84136EBF8D2603C2CD6668C955F920C6C6482EE4
PSParentPath : Microsoft.PowerShell.Security\Certificate::CurrentUser\My
PSChildName : 84136EBF8D2603C2CD6668C955F920C6C6482EE4
PSDrive : cert
PSProvider : Microsoft.PowerShell.Security\Certificate
PSIsContainer : False
Archived : False
Extensions : {System.Security.Cryptography.Oid}
FriendlyName :
IssuerName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
NotAfter : 12/31/2039 5:59:59 PM
NotBefore : 6/1/2012 1:49:31 PM
HasPrivateKey : True
PrivateKey : System.Security.Cryptography.RSACryptoServiceProvider
PublicKey : System.Security.Cryptography.X509Certificates.PublicKey
RawData : {48, 130, 1, 235...}
SerialNumber : CF330347F35AC0B4427AFFA82DB51238
SubjectName : System.Security.Cryptography.X509Certificates.X500DistinguishedName
SignatureAlgorithm : System.Security.Cryptography.Oid
Thumbprint : 84136EBF8D2603C2CD6668C955F920C6C6482EE4
Version : 3
Handle : 479608336
Issuer : CN=VetWeb CA
Subject : CN=VetWeb
Почему я могу подписывать с помощью файла signtool.exe, но не Powershell?
P.S. запуск Get-Childitem cert:\CurrentUser\My -CodeSigningCert
не возвращает результатов.
Ответы
Ответ 1
У меня была та же проблема, и я понял, что мне пришлось создать два сертификата. Во-первых, доверенный корневой центр сертификации с использованием
makecert -n "CN=PowerShell Local Certificate Root" -a sha1 -eku 1.3.6.1.5.5.7.3.3 -r -sv root.pvk root.cer -ss Root -sr localMachine
И затем персональный сертификат из вышеупомянутого центра сертификации с использованием
makecert -pe -n "CN=PowerShell User" -ss MY -a sha1 -eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer
После создания используйте
$cert = @(Get-ChildItem cert:\CurrentUser\My -CodeSigning)[0]
для подписания (при условии, что у вас есть только один сертификат для кодов). Например, если имя script - xyz.ps1, используйте эту команду в PowerShell
Set-AuthenticodeSignature path/to/xyz.ps1 $cert
Ответ 2
Согласно получить сертификат справки -CodeSigningCert
динамический параметр от поставщика сертификата получает только те сертификаты с полномочиями по подписи кода.
Теперь, почему signtool
может подписать, а не Set-AuthenticodeSignature
, объяснение может быть в Введение в подписание кода Документ Microsoft.
Вот моя версия генерации авторитета сертификации:
# Gen-CACert.ps1
clear-host
$scriptBlock = {.\Makecert -n `"CN=PowerShell Authorite de certification`" <# Sujet du certificat (conforme à la norme X50 #>`
-a sha1 <# Algorithme utilisé #>`
-eku 1.3.6.1.5.5.7.3.3 <# Option du certificat (signature de code) #>`
-r <# Certificat auto signé #>`
<# -ss `"$($args[0])`" Dossier de stockage du certificat #>`
-ss `"root`" <# Dossier de stockage du certificat #>`
-sr localMachine <# Magasin de stockage localmachine ou currentuser (defaut) #>`
-sv `"$($args[0]).pvk`" <# Nom du fichier contenant la clef privée #>`
`"$($args[0]).cer`"} <# Nom du fichier certificat #>
$PoshCARoot = "PoshCARoot"
Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $PoshCARoot
Вот моя версия генерации сертификата dev:
# Gen-DevCert.ps1
clear-host
$scriptBlock = {.\Makecert -pe <# La clef privée est exportable #>`
-n `"CN=PowerShell Dev Team`" <# Sujet du certificat (conforme à la norme X509 #>`
-a sha1 <# Algorithme utilisé #>`
-eku 1.3.6.1.5.5.7.3.3 <# Option du certificat (signature de code) #>`
-ss `"My`" <# Dossier de stockage du certificat #>`
-sr currentuser <# Magasin de stockage localmachine ou currentuser (defaut) #>`
-iv `"$($args[0]).pvk`" <# Clef privée de l'autorité #>`
-ic `"$($args[0]).cer`" <# Certificat de l'autorité #>`
`"$($args[1]).cer`"} <# Nom du fichier certificat #>
$PoshCARoot = "PoshCARoot"
$PoshDevTeam = "PoshDevTeam"
Invoke-Command -ScriptBlock $scriptBlock -ArgumentList $PoshCARoot,$PoshDevTeam
Ответ 3
Проблема заключается в том, что сертификат подписи искажен и отсутствуют правильные KU & EKUs. Я рекомендую использовать OpenSSL через openssl.cnf
для генерации сертификатов.
- Любой, кто нуждается в подписывающем сертификате, вероятно, имеет маршрутизатор с веб-администратором, может быть, NAS с веб-администратором, VPN-сервером и т.д., Каждый из которых должен иметь сертификаты SSL для шифрования TLS.
- Лучшая политика - создать центральный самоподписанный ЦС, используя
openssl
через openssl.cnf
, затем ICA для подписи кода (подписанный самоподписанным ЦС), который затем используется для подписи сертификата подписи кода.
- Windows: установить OpenVPN (включая
openssl-utils
)
- Добавить в PATH:
C:\Program Files\OpenVPN\bin
- BSD/Linux: Установить
openssl
|| openssl-utils
-
Готовый файл openssl.cnf содержит всю информацию & требуются команды, начиная со строки 430
- Создание CA требует 2 команды (создание и экспорт в PKCS12)
- Для создания ICA требуется 3 команды (создать, подписать и экспортировать в PKCS12)
- Для подписи Cert требуется 3 команды (создать, подписать и экспортировать в PKCS12)
- Раздел "Сертификаты клиента" - это то, что используется для подписания сертификатов
Сертификаты подписи кода должны иметь следующий набор:
keyUsage = critical, nonRepudiation, digitalSignature
nonRepudiation
- Сертификат может использоваться для подписи данных, как указано выше, но открытый ключ сертификата может использоваться для предоставления услуг, не вызывающих сомнений.
- Это предотвращает ложное отрицание подписывающим лицом какого-либо действия
digitalSignature
- Сертификат может быть использован для применения цифровой подписи
- Цифровые подписи часто используются для аутентификации объекта и аутентификация источника данных с целостностью
extendedKeyUsage = critical, codeSigning, msCodeInd, msCodeCom, mcCTLSign, timeStamping
codeSigning
msCodeInd
- Индивидуальная подпись кода Microsoft (authenticode)
msCodeCom
- Подписание коммерческого кода Microsoft (authenticode)
mcCTLSign
- Подписание списка доверия Microsoft
timeStamping
Инструмент для подписи
PreReqs:
-
Установить Windows SDK
- WinKey + R >
sysdm.cpl
> ОК
- Дополнительно> Переменные среды...> Путь> Изменить...
- Добавить в PATH:
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64
- Убедитесь, что
\10\bin\10.0.15063.0\x64
отражает правильный путь для вашего ПК и усилителя; OS
Команды:
-
set TS=http://sha256timestamp.ws.symantec.com/sha256/timestamp
- Устанавливает переменную
%TS%
для следующей команды
signtool sign /s my /fd SHA256 /ph /td SHA256 /tr %TS1% "Path\to\File"
sign
- Подписывать файлы с помощью встроенной подписи
/s
<name>
- Укажите Магазин, который нужно открыть при поиске сертификата. По умолчанию это магазин "MY".
/fd
- Определяет алгоритм дайджеста файла, который будет использоваться для создания подписей файлов. (По умолчанию SHA1)
/ph
- Создавайте хэши страниц для исполняемых файлов, если они поддерживаются.
/td
<alg>
-
Используется с переключателем
/tr
или /tseal для запроса алгоритма дайджеста, используемого сервером отметок времени RFC 3161.
/tr
<URL>
- Задает URL-адрес сервера меток времени RFC 3161. Если этот параметр (или
/t
) не указан, подписанный файл не будет иметь отметки времени. В случае сбоя метки времени выдается предупреждение. Этот переключатель нельзя использовать с переключателем /t
.
PowerShell
$Cert = Get-PfxCertificate -FilePath "Path\to\Signing\Cert"
- Устанавливает переменную
$Cert
для следующей команды
Set-Variable -Name TS -Value "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -Scope "Global"
- Устанавливает переменную
$TS
для следующей команды
Set-AuthenticodeSignature -HashAlgorithm "sha256" -IncludeChain "all" -FilePath "File" -Certificate $Cert -TimestampServer $TS
Set-AuthenticodeSignature
- Добавляет подпись Authenticode в сценарий PowerShell или другие файлы.
-HashAlgorithm
- Определяет алгоритм хеширования, используемый для вычисления цифровой подписи.
- PS 2.0: алгоритм хеширования по умолчанию - SHA1
- PS 3. 0+: алгоритм хеширования по умолчанию - SHA256
-IncludeChain
<String>
- Определяет, какие сертификаты в цепочке доверия сертификатов включены в цифровую подпись.
NotRoot
является значением по умолчанию. Допустимые значения для этого параметра:
Signer
: Включает только сертификат подписавшего.
NotRoot
: Включает все сертификаты в цепочку сертификатов, за исключением корневого центра.
All
: Включает все сертификаты в цепочку сертификатов.
-Certificate
<X509Certificate>
- Указывает сертификат, который будет использоваться для подписи скрипта или файла. Введите переменную, в которой хранится объект, представляющий сертификат, или выражение, которое получает сертификат.
- Чтобы найти сертификат, используйте
Get-PfxCertificate
или командлет Get-ChildItem
на диске Certificate (Cert :). Если сертификат недействителен или не имеет полномочий для подписи кода, команда не выполняется.