我有自签名代码签名证书(使用this answer的说明制作),当我使用signtool.exe
时,它可以正常工作。但是如果我尝试使用Powershell进行签名,则会失败。
使用signtool签名
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
不会返回任何结果。
答案 0 :(得分:9)
我有同样的问题,我想出的答案是我必须create two certificates。首先,使用
建立受信任的根证书颁发机构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]
用于签名(假设您只有一个代码签名证书)。例如,如果脚本的名称是xyz.ps1,请在PowerShell中使用此命令
Set-AuthenticodeSignature path/to/xyz.ps1 $cert
答案 1 :(得分:3)
根据get-help certificate -CodeSigningCert
来自证书提供商的动态参数仅获取具有代码签名权限的证书。
现在为什么signtool
可以签名而不是Set-AuthenticodeSignature
,解释可能在Introduction to Code Signing 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
这是我的开发版证书版本:
# 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
答案 2 :(得分:0)
问题是签名证书格式错误,错过了正确的KU&amp; EKUs。我个人建议通过openssl.cnf使用OpenSSL来生成证书。
openssl
通过openssl.cnf创建中心自签名CA的最佳策略,然后创建用于代码签名的ICA(由自签名CA签名),其中然后用来签署代码签名证书。C:\Program Files\OpenVPN\bin
代码签名证书应具有以下设置:
keyUsage = critical, nonRepudiation, digitalSignature
nonRepudiation
强>
digitalSignature
强>
extendedKeyUsage = critical, codeSigning, msCodeInd, msCodeCom, mcCTLSign, timeStamping
codeSigning
强>
msCodeInd
强>
msCodeCom
强>
mcCTLSign
强>
timeStamping
强>
PreReqs:
C:\Program Files (x86)\Windows Kits\10\bin\10.0.15063.0\x64
\10\bin\10.0.15063.0\x64
反映PC的正确路径命令:
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>
强>
/fd
强>
/ph
强>
/td
<alg>
强>
/tr
或 / tseal 开关一起使用,以请求RFC 3161时间戳服务器使用的摘要算法。* /tr
<URL>
强>
/t
),则签名文件将不会加时间戳。如果时间戳失败,则会生成警告。此开关不能与/t
开关一起使用。
$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
强>
-HashAlgorithm
强>
-IncludeChain
<String>
强>
NotRoot
是默认值。此参数的可接受值为:
Signer
: 仅包含签名者的证书。 NotRoot
: 包含证书链中的所有证书,但根权限除外。 All
: 包含证书链中的所有证书。 -Certificate
<X509Certificate>
强>
Get-PfxCertificate
或使用证书(Cert :)驱动器中的Get-ChildItem
cmdlet。如果证书无效或没有代码签名权限,则命令失败。