powershell Signtool允许我签署代码,但Set-AuthenticodeSignature说“证书不适合代码签名”

hivapdat  于 2023-05-17  发布在  Shell
关注(0)|答案(4)|浏览(235)

我有一个自签名的代码签名证书,是根据this answer的指示制作的,当与signtool.exe一起使用时,它可以正常工作,但是如果我尝试使用Set-AuthenticodeSignature签名,它会失败。
为什么我可以使用signtool签名,但不能使用Set-AuthenticodeSignature签名?

  • signtool
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
  • Set-AuthenticodeSignature
$cert = @(Get-Childitem cert:\CurrentUser\My | Where-Object -FilterScript {$_.Subject -eq 'CN=VetWeb'})[0]

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
  • Get-Childitem cert:\CurrentUser\My -CodeSigningCert未返回结果
$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
2fjabf4q

2fjabf4q1#

我也遇到了同样的问题,我想出的答案是我必须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
svdrlsy4

svdrlsy42#

问题是签名证书格式错误,缺少正确的KU和EKU。
要解决此问题,请使用以下链接的opensslopenssl.cnf创建一个自签名CA,创建一个由自签名CA签名的代码签名伊卡,最后创建一个由ICA签名的代码签名证书
预构建的openssl.cnf包含从第430行开始所需的所有信息和命令:

*前提条件:
***Windows:**安装OpenVPN(包括openssl-utils

  • (添加到系统PATH%ProgramFiles%\OpenVPN\bin)*
    ***BSD/Linux:**安装openssl|| openssl-utils|| Compile
    *创建CA:
# CA key should have a secure passphrase of at least 20 characters, containing 
# at least 2 uppercase, 2 lowercase, 2 numbers, and 2 symbols

# PreReqs: Create files crlnumber, index, rand, & serial
  mkdir cert crl 
  echo 01 > crl\crlnumber ; echo > index ; echo > rand ; echo 00 > serial

# Create CA:
  openssl req -x509 -new -sha512 -days 3650 -newkey rsa:4096 -keyout "CA.key.pem" -out "CA.crt.pem" -config "openssl.cnf" -extensions v3_ca

*创建伊卡:

# ICA key should have a secure passphrase of at least 20 characters, containing 
# at least 2 uppercase, 2 lowercase, 2 numbers, and 2 symbols

# Request:
  openssl req -out "code-signing-ICA.csr" -new -days 3650 -sha512 -newkey rsa:4096 -keyout "code-signing-ICA.key" -config "openssl.cnf" -extensions v3_signing_ica

# Sign:
  openssl x509 -req -sha512 -days 3650 -in "code-signing-ICA.csr" -CA "CA.crt.pem" -CAkey "CA.key.pem" -CAserial "serial" -out "code-signing-ICA.crt.pem" -extfile "openssl.cnf" -extensions v3_signing_ica

  # Create Concatenated CA - ICA Cert Chain:
    # Windows:
      cmd /c type "code-signing-ICA.crt.pem" "CA.crt.pem" > "code-signing-ICA-Chain.crt.pem"

    # BSD/Linux:
      cat "code-signing-ICA.crt.pem" "CA.crt.pem" > "code-signing-ICA-Chain.crt.pem"

*创建签名证书:

# Request:
  openssl req -out "code-signing.csr" -new -days 3650 -sha512 -newkey rsa:2048 -keyout "code-signing.key.pem" -config "openssl.cnf" -extensions v3_codesign

# Sign:
  openssl x509 -req -sha512 -days 3650 -in "code-signing.csr" -CA "code-signing-ICA-chain.crt.pem" -CAkey "code-signing-ICA.key.pem" -CAserial "serial" -out "code-signing.crt.pem" -extfile "openssl.cnf" -extensions v3_codesign

# Export:
  openssl pkcs12 -export -out "code-signing.p12" -inkey "code-signing.key.pem" -in "code-signing.crt.pem" -certfile "code-signing-ICA-chain.crt.pem"

OpenSSL KUs & EKUs

代码签名证书应具有以下设置:

keyUsage  = critical, nonRepudiation, digitalSignature

*nonRepudiation

证书可用于如上所述地签署数据,但证书公钥可用于提供不可否认服务

  • (防止签名实体错误地拒绝某些操作)*
    *digitalSignature

证书可用于应用数字签名

  • (用于实体认证和数据源完整性认证)*
extendedKeyUsage  = critical, codeSigning, msCodeInd, msCodeCom, mcCTLSign, timeStamping

*codeSigning

代码签名

*msCodeInd

Microsoft单独代码签名(authenticode)

*msCodeCom

Microsoft商业代码签名(authenticode)

*mcCTLSign

Microsoft信任列表签名

*timeStamping

可信时间戳

SignTool

先决条件:
1.安装Windows SDK
1.**

+R**→ sysdm.cpl → OK

  • 高级 * → * 环境变量…* → * 系统变量 * → * 路径 * → * 编辑…*
  • 添加到PATH:%ProgramFiles(x86)%\Windows Kits\10\bin\10.0.15063.0\x64
  • 确保\10\bin\10.0.15063.0\x64反映了Windows版本的正确路径
# Establish $TS variable:
  Set-Variable -Name TS -Value "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -Scope "Global"

# Sign:
  SignTool sign /s "MY" /fd "SHA256" /ph /td "SHA256" /tr $TS "Path\to\File"

*sign

使用嵌入式签名对文件进行签名

*/s<name>

指定搜索证书时要打开的存储 (默认值:MY商店)

*/fd

指定用于创建文件签名的文件摘要算法 (默认值:SHA1)

*/ph

为可执行文件生成页面哈希(如果支持)

*/td<alg>

/tr/tseal一起使用,请求RFC 3161时间戳服务器使用的摘要算法

*/tr<URL>

指定RFC 3161时间戳服务器的URL (如果时间戳失败,将生成警告)

  • 如果未指定/tr/t,则不会为签名文件添加时间戳

PowerShell

# Establish $cert variable:
  $cert = Get-PfxCertificate -FilePath "Path\to\Signing\Cert"

# Establish $TS variable (if not already set above):
  Set-Variable -Name TS -Value "http://sha256timestamp.ws.symantec.com/sha256/timestamp" -Scope "Global"

# Sign:
  Set-AuthenticodeSignature -HashAlgorithm "sha256" -IncludeChain "all" -FilePath "File"  -Certificate $cert -TimestampServer $TS

*Set-AuthenticodeSignature

将Authenticode签名添加到PowerShell脚本或其他文件

*-HashAlgorithm

指定用于计算数字签名的哈希算法

  • (PowerShell 2:sha1|| PowerShell 3+:sha256)*
    *-IncludeChain<String>

确定信任链中的哪些证书包含在数字签名 * 中(默认值:NotRoot)*;可接受值:

***Signer:**仅包含签名者的证书
***NotRoot:**包括证书链中除根颁发机构外的所有证书
***All:**包括证书链中的所有证书
*-Certificate<X509Certificate>

将用于对脚本或文件进行签名的证书;输入存储表示证书的对象或获取证书的表达式的变量

  • 要查找证书,请使用证书[Cert:]驱动器中的Get-PfxCertificateGet-ChildItem;如果证书无效或没有codeSigning权限,则命令失败
yvgpqqbh

yvgpqqbh3#

根据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
a11xaf1n

a11xaf1n4#

使用Set-AuthenticodeSignature时,签名证书必须包含增强密钥用法中的代码签名(1.3.6.1.5.5.7.3.3

我使用OpenSSL on Windows创建一个CA证书和一个签名证书来完成这项工作。
1.为签名证书生成私钥
openssl genrsa -des3 -out mycert.private.key 2048
1.从私钥创建证书签名请求
openssl req -key mycert.private.key -new -out mycert.csr
1.创建CA证书
openssl req -x509 -sha256 -days 10950 -newkey rsa:2048 -keyout rootCA. key-out rootCA.crt
1.创建用于签名证书的扩展文件
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
扩展密钥使用= 1.3.6.1.5.5.7.3.3
subjectAltName = @alt_names
[alt_名称]
DNS.1 = yourdns.net
1.使用CA证书签署证书
openssl x509 -req -CA rootCA.crt -CAkey rootCA.key -in mycert.csr -out mycert.crt -days 10950 -CAcreateserial -extfile mycert.ext
1.导出包含证书和私钥的PFX文件
openssl pkcs12 -export -in nzml.crt -inkey mycert.private.key -out mycert.pfx
1.将CA证书(rootCA.crt)导入开发计算机的受信任根证书颁发机构存储中

相关问题