简短说明
介绍如何对脚本进行签名,使其符合 PowerShell 执行策略。
详细说明
此信息仅适用于在 Windows 上运行的 PowerShell。
Restricted execution (受限执行) 策略不允许运行任何脚本。 AllSigned 和 RemoteSigned 执行策略可防止 PowerShell 运行没有数字签名的脚本。
本主题介绍即使在执行策略为 RemoteSigned的情况下,如何运行未签名的选定脚本,以及如何为脚本签名以供个人使用。
有关 PowerShell 执行策略的详细信息,请参阅 about_Execution_Policies。
允许已签名的脚本运行
首次在计算机上启动 PowerShell 时,受限 执行策略(默认值)可能生效。
Restricted 策略不允许运行任何脚本。
若要在计算机上查找有效的执行策略,请键入:
Get-ExecutionPolicy
要运行您在本地计算机上编写的未签名脚本以及来自其他用户的签名脚本,请使用 Run as Administrator (以管理员身份运行) 选项启动 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 或使用以下过程。
- 在计算机上保存脚本文件。
- 单击 “开始”,单击 “我的计算机”,然后找到保存的脚本文件。
- 右键单击脚本文件,然后单击 属性。
- 单击 取消阻止。
如果从 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 不会再次提示你是否信任此发布者。
签署脚本的方法
可以对所编写的脚本和从其他源获取的脚本进行签名。 在对任何脚本进行签名之前,请检查每个命令,以验证其是否安全运行。
有关代码签名的最佳实践,请参阅 Code-Signing 最佳实践。
有关如何对脚本文件进行签名的详细信息,请参阅 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 中。
若要导出证书,请执行以下操作:
- 启动证书管理器。
- 选择 PowerShell 本地证书根颁发的证书。
- 单击 导出 启动证书导出向导。
- 选择“是,导出私钥” ,并单击“下一步” 。
- 选择启用强保护。
- 键入密码,然后再次键入密码进行确认。
- 键入具有
.pfx文件扩展名的文件名。 - 单击“完成”。
若要重新导入证书,请执行以下操作:
- 启动证书管理器。
- 单击 导入 启动证书导入向导。
- 打开导出过程中创建的
.pfx文件的位置。 - 在“密码”页上,选择 “启用强私钥保护”,然后输入在导出过程中分配的密码。
- 选择 “个人 证书存储”。
- 单击“完成”。
阻止签名过期
脚本中的数字签名在签名证书过期之前有效,或者只要时间戳服务器可以验证脚本在签名证书有效时是否已签名。
由于大多数签名证书仅有效期为一年,因此使用时间戳服务器可确保用户在未来几年内可以使用脚本。