是否有一种简单的方法可以检查文件上是否存在数字签名,而无需验证其签名的证书?
我想签一长串的exe &DLL文件,但仅限于尚未签名的文件。
例如,如果其中一个文件已经被微软或其他第三方签名,我不想用我公司的证书再次签名。
很容易检查文件是否有数字签名,右键单击文件并查看其属性(如果数字签名选项卡显示,那么它已被签名)。我正在寻找一个简单的方法来检查这个数字签名属性使用c#。
现在,我正在使用signtool.exe的verify命令-它不仅检查数字签名是否存在,而且还检查用于签名文件的证书是否由受信任的机构颁发。
这是我的简单而笨拙的方法:
private static Boolean AlreadySigned(string file)
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.FileName = "signTool.exe";
startInfo.Arguments = "verify /v " + file;
startInfo.UseShellExecute = false;
Process process = new Process();
process.StartInfo = startInfo;
process.EnableRaisingEvents = true;
process.Start();
process.WaitForExit();
string output = process.StandardOutput.ReadToEnd();
return output.Contains("Signing Certificate Chain:");
}
请注意,我使用了详细标志"/v",并检查输出是否包含文本"Signing Certificate chain:" -只是因为我注意到该字符串总是在已签名的文件的输出中-并且在未签名的文件中被省略。
无论如何,尽管它很笨拙,这段代码似乎完成了工作。我想更改它的一个原因是,在文件上执行verify命令似乎需要几百毫秒的时间。我不需要验证证书,我只是想看看文件上是否存在数字签名。
所以简而言之,有没有一种简单的方法来检查数字签名是否存在——而不需要验证它?
我想出了一个相当不错的解决方案,使用"Get-AuthenticodeSignature" powershell命令。我发现这个网站解释了如何在c#中使用powershell命令。这样我就不需要生成几个进程,而且非常快。
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
private static Boolean alreadySigned(string file)
{
try
{
RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create();
Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration);
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Get-AuthenticodeSignature "" + file + """);
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
Signature signature = results[0].BaseObject as Signature;
return signature == null ? false : (signature.Status != SignatureStatus.NotSigned);
}
catch (Exception e)
{
throw new Exception("Error when trying to check if file is signed:" + file + " --> " + e.Message);
}
}
如果你想为。net程序集这样做,你可以这样做:
string filePath = "C:/path/to/file.dll";
Assembly assembly = Assembly.LoadFrom(filePath);
Module module = assembly.GetModules().First();
X509Certificate certificate = module.GetSignerCertificate();
if (certificate == null)
{
// file is not signed.
}
X509Certificate
类有一些静态方法可能也有用(例如CreateFromSignedFile
),但我对它们不太熟悉。这是我们用来反复检查数字签名是否被我们的内部工具应用的方法。
首先,signtool只适用于PE文件。对于其他文件类型,可以使用包装签名或嵌入签名或分离签名进行签名。
包装签名会改变实际文件,使通常用来读取它的应用程序无法读取它。如。如果您在PDF上创建了包装签名,则在删除签名之前,任何PDF工具都无法读取该文件。
一些文件格式在其格式中支持嵌入签名(例如EXE文件和Authenticode格式)。在那里,你可以将签名嵌入到文件中,而其他应用程序仍然可以读取它。但这是特定于格式的,并不是很多格式都支持。
最后,分离的签名与文件分开保存。例如,如果您有一个文件a.txt
,则创建一个分离的签名并将其放入a.txt.pkcs7detached
中。
我们SecureBlackbox产品的PKIBlackbox包支持以上所有签名类型