我在构建期间对许多 PowerShell 文件进行了代码签名。
根据调用 Get-AuthenticodeSignature
的方式,我得到不同的签名状态:
PS> Get-ChildItem | ForEach { Get-AuthenticodeSignature $_.Name }
SignerCertificate Status Path
----------------- ------ ----
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid CleanUpdateParameters.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid CreateApplication.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid DeleteApplication.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid ProvisionApplicationType.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid UnprovisionApplicationType.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid UpdateParameters.ps1
一切看起来都很好。但这是我尝试使用二进制内容验证文件时的结果:
PS> Get-ChildItem | ForEach { Get-AuthenticodeSignature -Content ([System.IO.File]::ReadAllBytes($_.FullName)) -SourcePathOrExtension $_.Name }
SignerCertificate Status Path
----------------- ------ ----
NotSigned CleanUpdateParameters.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid CreateApplication.ps1
NotSigned DeleteApplication.ps1
NotSigned ProvisionApplicationType.ps1
NotSigned UnprovisionApplicationType.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid UpdateParameters.ps1
或字符串内容:
PS> Get-ChildItem | ForEach { Get-AuthenticodeSignature -Content ([System.Text.Encoding]::ASCII.GetBytes([System.IO.File]::ReadAllText($_.FullName))) -SourcePathOrExtension $_.Name }
SignerCertificate Status Path
----------------- ------ ----
NotSigned CleanUpdateParameters.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid CreateApplication.ps1
NotSigned DeleteApplication.ps1
NotSigned ProvisionApplicationType.ps1
NotSigned UnprovisionApplicationType.ps1
E36170335E3DD78B6CDF1594B0D164F7C8A7B324 Valid UpdateParameters.ps1
我已经花了一个星期的时间来解决这个问题,无法理解导致这种差异/不一致的原因。我必须让它正常工作,因为我的应用程序(“客户端”)从服务(“服务器”)接收脚本作为字符串,并且必须验证内容的有效性。
最佳答案
遗憾的是,Get-AuthenticodeSignature -Content
只能识别表示“Unicode”(UTF-16LE) 编码字符的字节数组 - 任何其他编码都被错误地表示为 NotSigned
在输出中。
参见 this GitHub issue .
您的症状意味着只有脚本 CreateApplication.ps1
和 UpdateParameters.ps1
是 UTF-16LE 编码的。
如果您想对所有脚本使用 -Content
:
- 任一个:将所有脚本文件转码为 UTF-16LE(使用该编码保存它们)。
- 或:传递表达式
([Text.Encoding]::Unicode.GetPreamble() +[Text.Encoding]::Unicode.GetBytes((Get-Content -Raw $_ .FullName)))
为-Content
,即手动将文件内容转为UTF-16LE字节;请注意需要明确地在 BOM 前添加(序言))。
正如您所观察到的,使用(隐含的)参数 -FilePath
- 即传递一个文件路径并让 Get-AuthenticodeSignature
本身读取它的内容 - 不受此编码限制 - 只要 PowerShell 可以按照通常的规则推断脚本文件的编码,签名验证就会成功。
关于powershell - 从 PowerShell 调用 Get-AuthenticodeSignature 的结果不一致,通常说 NotSigned,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53712247/