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

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

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

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

  • 创建的证书:可以创建自签名证书,计算机是创建证书的颁发机构。 此证书是免费的,可用于在计算机上编写、签名和运行脚本。 但是,由自签名证书签名的脚本不会在其他计算机上运行。

通常,只能使用自签名证书来签署你为自己使用而编写的脚本,并签署你从已验证为安全的其他源获取的脚本。 它不适用于将共享的脚本,即使在企业中也是如此。

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

创建自签名证书

若要创建自签名证书,请使用 PKI 模块中的 New-SelfSignedCertificate cmdlet。 PowerShell 3.0 中引入了此模块。 有关详细信息,请参阅 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 会提示输入私钥密码。 密码可确保未经你的同意,任何人都无法使用或访问证书。 Create并输入可记住的密码。 稍后将使用此密码来检索证书。

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

在 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. 单击“完成”。

防止签名过期

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

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

另请参阅