about_Signing
简短说明
介绍如何对脚本进行签名,使其符合 PowerShell 执行策略。
长说明
此信息仅适用于在 Windows 上运行的 PowerShell。
受限执行策略不允许运行任何脚本。 AllSigned 和 RemoteSigned 执行策略阻止 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 或使用以下过程。
- 在计算机上保存脚本文件。
- 单击“ 开始”,单击“ 我的电脑”,并找到保存的脚本文件。
- 右键单击脚本文件,然后单击“ 属性”。
- 单击“ 取消阻止”。
如果从 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 中。
导出证书:
- 启动证书管理器。
- 选择 PowerShell 本地证书根颁发的证书。
- 单击“ 导出 ”启动证书导出向导。
- 选择“是,导出私钥” ,并单击“下一步” 。
- 选择“ 启用强保护”。
- 键入密码,然后再次键入以确认。
- 键入文件扩展名为 的
.pfx
文件名。 - 单击“完成”。
若要重新导入证书,请执行以下操作:
- 启动证书管理器。
- 单击“ 导入 ”以启动证书导入向导。
- 打开到导出过程中创建的文件的位置
.pfx
。 - 在“密码”页上,选择“ 启用强私钥保护”,然后输入在导出过程中分配的密码。
- 选择“个人”证书存储。
- 单击“完成”。
防止签名过期
脚本中的数字签名在签名证书过期之前有效,或者只要时间戳服务器可以在签名证书有效时验证脚本是否已签名。
由于大多数签名证书的有效期仅为一年,因此使用时间戳服务器可确保用户在未来很多年内都可以使用脚本。