about_Signing

简短说明

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

长说明

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

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

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

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

允许已签名的脚本运行

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

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

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

Get-ExecutionPolicy

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

Set-ExecutionPolicy RemoteSigned

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

使用 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 中引入,并包含在Windows 8和Windows Server 2012中。 有关详细信息,请参阅 cmdlet 的 New-SelfSignedCertificate 帮助主题。

$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
param([string] $file=$(throw "Please specify a filename."))
$cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]
Set-AuthenticodeSignature $file $cert

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

$cert = @(Get-ChildItem cert:\CurrentUser\My -codesigning)[0]
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. 单击“完成”。

阻止签名过期

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

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

另请参阅