从 PowerShell 调用 Get-AuthenticodeSignature 的结果不一致,通常说 NotSigned

Inconsistency in results of calling Get-AuthenticodeSignature from PowerShell, often says NotSigned

我在构建期间对许多 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

我已经花了一个星期的时间来解决这个问题,无法理解是什么导致了这个 discrepancy/inconsistency。我必须让它工作,因为我的应用程序 ('client') 从服务 ('server') 接收脚本作为字符串,并且必须验证内容的有效性。

遗憾的是,Get-AuthenticodeSignature -Content 只能识别表示 "Unicode" (UTF-16LE) 编码字符的字节数组 - 任何其他编码都被错误表示为 NotSigned 在输出中。
参见 this GitHub issue

您的症状表明只有脚本 CreateApplication.ps1UpdateParameters.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 本身读取其 contents - 不受此编码限制 - 只要 PowerShell 可以按照通常的规则推断脚本文件的编码,签名验证就会成功。