我想以编程方式检查文件是否已经过数字签名.
目前,我在MSDN中发现了一个相当模糊的代码,它无法编译......
关于这个问题的任何想法?
顺便说一句,带命令行的外部工具也很棒.
提到signtool的答案中重要的缺失部分是:
是的,使用众所周知的signtool.exe,如果文件已签名,您也可以找到.无需下载其他工具!
例如,简单的线条:
signtool verify /pa myfile.exe if %ERRORLEVEL% GEQ 1 echo This file is not signed.
(对于详细输出,在'/ pa'之后添加'/ v'.)
有人可能会问:为什么这很重要?我只是签署文件(再次),这些文件应该签名并且有效.
我的目标是保持构建清洁,不要再次签署文件,因为不仅日期已更改,而且之后二进制文件也不同.
业务示例:我的客户端具有简化的自动"开发操作"类型构建和后期构建过程.不同的文件集有多个来源,最后都是构建,测试和捆绑到分发 - 并且为此必须签署一些文件.为了保证某些文件不会在没有签名的情况下离开本机,我们就会签署所有重要文件,即使它们已经签名.
但这还不够干净:
1)如果我们再次签署一个已经签名的文件,则文件日期和二进制指纹会发生变化,如果只是简单地复制了文件,那么该文件就会失去与其来源的可比性.(至少如果您使用时间戳签名,我们总是这样做,我认为强烈建议.)
这是严重的质量损失,因为此文件不再与其他文件源的前辈相当.
2)如果我们再次签署文件,这也可能是一个错误,它是第三方文件,不应由您的单位签署.
您可以通过使签名本身具有条件来避免这两种情况,具体取决于前面提到的"signtool verify"调用的返回代码.
下载Sigcheck y使用以下命令.
sigcheck.exe -a -u -e
签名dll的示例
无符号dll的示例
Sigcheck是一个显示文件版本号的命令行实用程序.祝好运
如果需要外部工具,可以使用signtool.exe.它是Windows SDK的一部分,它需要命令行参数,你可以在这里找到更多相关信息,http://msdn.microsoft.com/en-us/library/aa387764.aspx
我在网上找到了另一种选择(纯的.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; namespace ConsoleApplication1 { 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)"); } } } }