Определение наличия у файла цифровой подписи в C# без фактической проверки подписи
Есть ли простой способ проверить, существует ли цифровая подпись в файле, не пытаясь проверить сертификат, с которым он был подписан?
Я хочу подписать длинный список файлов exe & dll в каталоге, но только файлы, которые еще не были подписаны.
Например, если один из файлов был подписан Microsoft или какой-либо другой третьей стороной, я не хочу подписывать их снова сертификатом моей компании.
Легко проверить, имеет ли файл цифровую подпись или нет, щелкнув файл правой кнопкой мыши и просмотрев его свойства (если отображается вкладка цифровой подписи, значит, он был подписан). Я ищу простой способ проверить это свойство цифровой подписи с помощью C#.
Прямо сейчас я использую команду verify с signtool.exe - которая не только проверяет, существует ли цифровая подпись, но также и был ли сертификат, использованный для подписи файла, выпущен доверенным органом.
Вот мой простой, но неуклюжий подход для этого:
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" и проверяю, содержит ли вывод текст "Цепочка сертификата подписи:" - только потому, что я заметил, что эта строка всегда была в выводе файла, который был подписан - и был исключено из любого файла, который не был подписан.
В любом случае, несмотря на свою неуклюжесть, этот код, похоже, выполняет свою работу. Одна из причин, по которой я хотел бы изменить его, заключается в том, что выполнение команды проверки файла занимает несколько сотен миллисекунд. Мне не нужно проверять сертификат, я просто пытаюсь проверить, существует ли цифровая подпись в файле.
Короче говоря, есть ли простой способ проверить, существует ли цифровая подпись - не пытаясь проверить это?
3 ответа
Я придумал довольно приличное решение, используя команду powershell "Get-AuthenticodeSignature". Я нашел этот сайт, который объясняет, как использовать команды powershell в C#. Таким образом, мне не нужно создавать несколько процессов, и это довольно быстро.
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
,
Как видите, отдельные подписи являются оптимальными для вашей задачи. И в этом случае у вас есть список файлов.pkcs7detached, так что вы можете проверить - если файл не имеет соответствующего файла.pkcs7detached с подписью, вы создаете новую подпись.
Все вышеперечисленные типы подписей поддерживаются пакетом PKIBlackbox нашего продукта SecureBlackbox.