我想以编程方式检查文件是否已进行数字签名。
目前,我发现了一个相当晦涩的Microsoft 代码,它无法编译......
对这个主题有任何想法吗?
顺便说一句,带有命令行的外部工具也很棒。
答案提到的重要缺失部分signtool
是:
是的,您还可以通过众所周知的signtool.exe
方式找出文件是否已签名。无需下载其他工具!
例如用简单的线:
signtool verify /pa myfile.exe
if %ERRORLEVEL% GEQ 1 echo This file is not signed.
(对于详细输出,请在/v
之后添加/pa
。)
有人可能会问:为什么这很重要?我只是(再次)签署应该签署的文件并且它可以工作。
我的目标是保持构建干净,并且不要第二次签署文件,因为不仅日期改变了,而且之后的二进制文件也不同。
业务示例:我的客户有一个简化的自动化“开发操作”类构建和构建后流程。不同的文件集有多个来源,最后所有文件都经过构建、测试和捆绑分发 - 为此必须对一些文件进行签名。为保证某些文件在没有签名的情况下不会离开设备,我们曾经对媒体上找到的所有重要文件进行签名,即使它们已经签名。
但这还不够干净!一般来说:
这是一个严重的质量损失,因为尽管文件本身没有更改,但该文件不再与其前身相同。
您可以通过根据前面提到的调用的返回码使签名本身有条件来避免这两种情况signtool verify
。
下载Sigcheck
并使用以下命令。
sigcheck.exe -a -u -e
已签名 dll 的示例
File version: 0.0.0.0
Strong Name: Signed
未签名 dll 的示例
File version: 0.0.0.0
Strong Name: Unsigned
Sigcheck
是一个显示文件版本号的命令行实用程序。祝你好运
我在网上找到了另一个选项(纯 .NET 代码)。
该代码非常简单并且有效。
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Threading.Tasks;
internal class Program
{
private static void Main(string[] args)
{
string filePath = args[0];
if (!File.Exists(filePath))
{
Console.WriteLine("File not found");
return;
}
X509Certificate2 theCertificate;
try
{
X509Certificate theSigner = X509Certificate.CreateFromSignedFile(filePath);
theCertificate = new X509Certificate2(theSigner);
}
catch (Exception ex)
{
Console.WriteLine("No digital signature found: " + ex.Message);
return;
}
bool chainIsValid = false;
/*
*
* This section will check that the certificate is from a trusted authority IE
* not self-signed.
*
*/
var theCertificateChain = new X509Chain();
theCertificateChain.ChainPolicy.RevocationFlag = X509RevocationFlag.ExcludeRoot;
/*
*
* Using .Online here means that the validation WILL CALL OUT TO THE INTERNET
* to check the revocation status of the certificate. Change to .Offline if you
* don't want that to happen.
*/
theCertificateChain.ChainPolicy.RevocationMode = X509RevocationMode.Online;
theCertificateChain.ChainPolicy.UrlRetrievalTimeout = new TimeSpan(0, 1, 0);
theCertificateChain.ChainPolicy.VerificationFlags = X509VerificationFlags.NoFlag;
chainIsValid = theCertificateChain.Build(theCertificate);
if (chainIsValid)
{
Console.WriteLine("Publisher Information : " + theCertificate.SubjectName.Name);
Console.WriteLine("Valid From: " + theCertificate.GetEffectiveDateString());
Console.WriteLine("Valid To: " + theCertificate.GetExpirationDateString());
Console.WriteLine("Issued By: " + theCertificate.Issuer);
}
else
{
Console.WriteLine("Chain Not Valid (certificate is self-signed)");
}
}
}
如果需要外部工具,可以使用 signtool.exe。它是 Windows SDK 的一部分,它接受命令行参数,你可以在这里找到更多关于它的信息, http: //msdn.microsoft.com/en-us/library/aa387764.aspx
从 PowerShell 5.1 开始,您可以使用它Get-AuthenticodeSignature
来验证二进制文件或 PowerShell 脚本的签名。
> Get-AuthenticodeSignature -FilePath .\MyFile.exe
SignerCertificate Status Path
----------------- ------ ----
A59E92E31475F813DDAF41C3CCBC8B78 Valid MyFile.exe
或者
> (Get-AuthenticodeSignature -FilePath .\MyFile.exe).Status
Valid
您也可以尝试为此sign-check
目的使用 npm 包。
这个包实现了 WinVerifyTrust API 并且使用简单:
npm install -g sign-check
sign-check 'path/to/file'