about_Signing

简短说明

介绍如何对脚本进行签名,使其符合 PowerShell 执行策略。

长说明

此信息仅适用于在 Windows 上运行的 PowerShell。

受限执行策略不允许运行任何脚本。 AllSignedRemoteSigned 执行策略阻止 PowerShell 运行无数字签名的脚本。

本主题介绍如何运行未签名的选定脚本(即使执行策略为 RemoteSigned),以及如何对脚本进行签名以供自己使用。

PowerShell 检查以下类型类型的 Authenticode 签名:

  • .ps1 脚本文件
  • .psm1 模块文件
  • .psd1 模块清单和数据文件
  • .ps1xml 类型和格式化 XML 文件
  • .cdxml CDXML 脚本文件
  • .xaml XAML 脚本文件

有关 PowerShell 执行策略的详细信息,请参阅 about_Execution_Policies

允许签名的脚本运行

首次在计算机上启动 PowerShell 时,Restricted 执行策略(默认设置)可能会生效。

Restricted 策略不允许运行任何脚本。

若要在计算机上查找生效的执行策略,请键入:

Get-ExecutionPolicy

若要在本地计算机上运行你编写的未签名脚本以及其他用户编写的已签名脚本,请使用“以管理员身份运行”选项启动 PowerShell,然后使用以下命令将计算机上的执行策略更改为 RemoteSigned

Set-ExecutionPolicy RemoteSigned

有关详细信息,请参阅 Set-ExecutionPolicy cmdlet 的帮助主题。

使用 RemoteSigned 执行策略运行未签名脚本

如果 PowerShell 执行策略是 RemoteSigned,PowerShell 不会运行从 Internet 下载的未签名脚本,包括通过电子邮件和即时消息程序收到的未签名脚本。

如果你尝试运行下载的脚本,PowerShell 会显示以下错误消息:

The file <file-name> cannot be loaded. The file <file-name> is not
digitally signed. The script will not execute on the system. Please see
"Get-Help about_Signing" for more details.

在运行脚本之前,请查看代码以确保它可信。 脚本与任何可执行程序的效果相同。

若要运行未签名脚本,请使用 Unblock-File cmdlet 或使用以下过程。

  1. 在计算机上保存脚本文件。
  2. 依次单击“开始”、“我的电脑”,然后找到保存的脚本文件。
  3. 右键单击该脚本文件,然后单击“属性”。
  4. 单击“取消阻止”。

如果从 Internet 下载的脚本经过数字签名,但你暂时还不能信任其发布者,PowerShell 会显示以下消息:

Do you want to run software from this untrusted publisher?
The file <file-name> is published by CN=<publisher-name>. This
publisher is not trusted on your system. Only run scripts
from trusted publishers.

[V] Never run  [D] Do not run  [R] Run once  [A] Always run
[?] Help (default is "D"):

如果你信任发布者,请选择“运行一次”或“始终运行”。 如果你不信任发布者,请选择“从不运行”或“不运行”。 如果选择“从不运行”或“始终运行”,PowerShell 不会再次提示你是否信任此发布者。

脚本签名的方法

可以对编写的脚本和从其他源获取的脚本进行签名。 在对任何脚本签名之前,请检查每个命令,以验证是否可以安全运行。

有关代码签名的最佳做法,请参阅代码签名最佳做法

有关如何对脚本文件进行签名的详细信息,请参阅 Set-AuthenticodeSignature

PowerShell 3.0 的 PKI 模块中引入的 New-SelfSignedCertificate cmdlet 可创建适合测试的自签名证书。 有关详细信息,请参阅 New-SelfSignedCertificate cmdlet 的帮助主题。

若要向脚本添加数字签名,必须使用代码签名证书对其进行签名。 有两种类型的证书适用于对脚本文件进行签名:

  • 证书颁发机构创建的证书:公共证书颁发机构会验证你的身份,并提供代码签名证书(收费)。 从信誉良好的证书颁发机构购买证书后,你可以与其他运行 Windows 的计算机上的用户共享脚本,因为其他这些计算机信任该证书颁发机构。

  • 你创建的证书:你可以创建自签名证书,对于这种情况,计算机是创建该证书的颁发机构。 此证书免费,使你能够在计算机上编写、签名和运行脚本。 但是,由自签名证书签名的脚本不能在其他计算机上运行。

通常,你会使用自签名证书来仅对你编写的、供自己使用的脚本进行签名,并签名从已验证为安全的其他源获取的脚本。 它不适用于共享的脚本,即使在企业内也是如此。

如果创建自签名证书,必须在证书上启用强私钥保护。 这可以防止恶意程序代表你对脚本进行签名。 本主题末尾包含了相关说明。

创建自签名证书

若要创建自签名证书,请在 PKI 模块中使用 New-SelfSignedCertificate cmdlet。 此模块是在 PowerShell 3.0 中引入的。 有关详细信息,请参阅 New-SelfSignedCertificate cmdlet 的帮助主题。

$params = @{
    Subject = 'CN=PowerShell Code Signing Cert'
    Type = 'CodeSigning'
    CertStoreLocation = 'Cert:\CurrentUser\My'
    HashAlgorithm = 'sha256'
}
$cert = New-SelfSignedCertificate @params

使用 Makecert.exe

若要在早期版本的 Windows 中创建自签名证书,请使用证书创建工具 MakeCert.exe。 此工具包含在 Microsoft .NET SDK(版本 1.1 及更高版本)和 Microsoft Windows SDK 中。

有关 MakeCert.exe 工具语法和参数说明的详细信息,请参阅证书创建工具 (MakeCert.exe)

若要使用 MakeCert.exe 工具创建证书,请在 SDK 命令提示符窗口中运行以下命令。

注意

第一个命令为计算机创建本地证书颁发机构。 第二个命令从证书颁发机构生成个人证书。 你可以完全按照显示内容复制或键入命令。 无需替换,不过可以更改证书名称。

makecert -n "CN=PowerShell Local Certificate Root" -a sha256 `
-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 sha256 `
-eku 1.3.6.1.5.5.7.3.3 -iv root.pvk -ic root.cer

MakeCert.exe 工具会提示你输入私钥密码。 密码可确保没有人能够在未经你同意的情况下使用或访问该证书。 创建并输入可记住的密码。 稍后将使用此密码检索证书。

若要验证证书是否已正确生成,请使用以下命令在计算机上的证书存储中获取证书。 在文件系统目录中找不到证书文件。

在 PowerShell 提示符处,键入:

Get-ChildItem cert:\CurrentUser\my -codesigning

此命令使用 PowerShell 证书提供程序查看有关证书的信息。

如果创建了证书,则输出会显示指纹,该指纹在如下所示的显示画面中标识证书:

Directory: Microsoft.PowerShell.Security\Certificate::CurrentUser\My

Thumbprint                                Subject
----------                                -------
4D4917CB140714BA5B81B96E0B18AAF2C4564FDF  CN=PowerShell User ]

对脚本进行签名

创建自签名证书后,可以对脚本进行签名。 如果使用 AllSigned 执行策略,则对脚本进行签名可以在计算机上运行脚本。

以下示例脚本 Add-Signature.ps1 对脚本进行签名。 但是,如果使用 AllSigned 执行策略,则必须在运行 Add-Signature.ps1 脚本之前对其进行签名。

重要

在 PowerShell 7.2 之前,必须使用 ASCII 或 UTF8NoBOM 编码保存脚本。 PowerShell 7.2 及更高版本支持任何编码格式的签名脚本。

若要使用此脚本,请将以下文本复制到文本文件中,并将其命名为 Add-Signature.ps1

## Signs a file
[cmdletbinding()]
param(
    [Parameter(Mandatory=$true)]
    [string] $File
)

$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert |
    Select-Object -First 1

Set-AuthenticodeSignature -FilePath $File -Certificate $cert

若要对 Add-Signature.ps1 脚本文件进行签名,请在 PowerShell 命令提示符下键入以下命令:

$cert = Get-ChildItem Cert:\CurrentUser\My -CodeSigningCert |
    Select-Object -First 1

Set-AuthenticodeSignature add-signature.ps1 $cert

对脚本进行签名后,可以在本地计算机上运行该脚本。 但是,脚本无法在其中的 PowerShell 执行策略需要受信任颁发机构提供的数字签名的计算机上运行。 如果你尝试运行,PowerShell 会显示以下错误消息:

The file C:\remote_file.ps1 cannot be loaded. The signature of the
certificate cannot be verified.
At line:1 char:15
+ .\ remote_file.ps1 <<<<

如果在运行不是由你编写的脚本时 PowerShell 显示此消息,请像处理任何未签名脚本一样处理该文件。 查看代码以确定是否可以信任该脚本。

为私钥启用强保护

如果计算机上具有私钥和证书,恶意程序可能能够代表你对脚本进行签名,从而授权 PowerShell 运行这些脚本。

若要防止恶意程序代表你自动签名,请使用证书管理器 Certmgr.exe 将签名密钥和证书导出到 .pfx 文件。 证书管理器包含在 Microsoft .NET SDK、Microsoft Windows SDK 和 Internet Explorer 中。

若要导出证书,请执行以下操作:

  1. 启动证书管理器。
  2. 选择 PowerShell 本地证书根颁发的证书。
  3. 单击“导出”以启动证书导出向导。
  4. 选择“是,导出私钥” ,并单击“下一步” 。
  5. 选择“启用强保护”。
  6. 键入密码,然后再次键入以确认。
  7. 键入具有 .pfx 文件扩展名的文件名。
  8. 单击“完成” 。

若要重新导入证书,请执行以下操作:

  1. 启动证书管理器。
  2. 单击“导入”以启动证书导入向导。
  3. 打开在导出过程中创建的 .pfx 文件。
  4. 在“密码”页上,选择“启用强私钥保护”,然后输入在导出过程中分配的密码。
  5. 选择“个人”证书存储。
  6. 单击“完成” 。

防止签名过期

脚本中的数字签名在签名证书过期之前有效,或者只要时间戳服务器可以验证脚本在签名证书有效时已签名,该数字签名即保持有效。

由于大多数签名证书有效期仅为一年,因此使用时间戳服务器可确保用户在未来几年内可以使用你的脚本。

另请参阅