14

我有一个自签名的代码签名证书,根据这个答案的说明制作,与 一起使用时效果很好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
    
4

3 回答 3

11

我遇到了同样的问题,我想出的答案是我必须创建两个证书。首先,一个受信任的根证书颁发机构使用

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
于 2013-09-03T03:42:41.723 回答
4

根据证书提供者的get-help 证书 -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

这是我的开发证书生成版本:

# 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
于 2012-06-07T20:18:11.143 回答
3

问题是签名证书格式错误并且缺少正确的 KU 和 EKU。

openssl要解决此问题,请使用下面的链接创建一个自签名 CA openssl.cnf,一个由自签名 CA 签名的代码签名 ICA,最后是一个由 ICA 签名的代码签名证书


预建openssl.cnf包含从第 430 行开始所需的所有信息和命令:

  1. 先决条件:
    • Windows安装OpenVPN(包括openssl-utils
      (添加到系统PATH:)%ProgramFiles%\OpenVPN\bin
    • BSD/Linux :安装openssl|| openssl-utils|| 编译
  2. 创建 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
    
  3. 创建 ICA:
    # 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"
    
  4. 创建签名证书:
    # 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 KU 和 EKU

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

  • keyUsage  = critical, nonRepudiation, digitalSignature
    
    • nonRepudiation
      证书可用于对上述数据进行签名,但证书公钥可用于提供不可否认服务
      (防止签名实体错误地拒绝某些操作)
    • digitalSignature
      证书可用于应用数字签名
      (用于实体认证和数据源完整性认证)

  • extendedKeyUsage  = critical, codeSigning, msCodeInd, msCodeCom, mcCTLSign, timeStamping
    
    • codeSigning:
      代码签名
    • msCodeInd:
      Microsoft 个人代码签名 (authenticode)
    • msCodeCom:
      微软商业代码签名 (authenticode)
    • mcCTLSign:
      微软信任列表签名
    • timeStamping:
      可信时间戳


SignTool

先决条件:

  1. 安装Windows SDK
  2. WinKey+Rsysdm.cpl→ 确定
    高级环境变量...系统变量路径编辑...
  3. 添加到路径:%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请求 RFC3161 时间戳服务器使用的摘要算法
  • /tr<URL>:
    指定 RFC3161 时间戳服务器的 URL (如果时间戳失败会产生警告)
    • 如果未指定/tr或未/t指定,则签名文件将不加时间戳


电源外壳

# 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>
    将用于签署脚本或文件的证书;输入存储表示证书的对象的变量或获取证书的表达式
    • 要查找证书,请使用证书 [ ] 驱动器中的Get-PfxCertificate或;如果证书无效或没有权限,则命令失败Get-ChildItemCert:codeSigning
于 2017-10-12T15:52:16.080 回答