Question

Is there a simple way to check if a digital signature exists on a file without trying to verify the certificate it was signed with?

I want to sign a long list of exe & dll files in a directory, but only files that haven't yet been signed.

For example, if one of the files has been signed by Microsoft or some other 3rd party I don't want to sign them again with my company's certificate.

It is easy to check if a file has a digital signature or not by right-clicking the file and viewing its properties (if the digital signature tab shows up then it has been signed). I'm searching for a simple way to check for this digital signature property using C#.

Right now, I am using the verify command with signtool.exe - which doesn't only check to see if a digital signature exists, but also whether the certificate used to sign the file was issued by a trusted authority.

Here is my simple, yet clunky approach for doing this:

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:");
}

Notice that I'm using the verbose flag "/v" and checking if the output contains the text "Signing Certificate chain:" - just because I noticed that that string was always in the output of a file that had been signed - and was omitted from any file that hadn't been signed.

Anyway, despite its clumsiness, this code seems to get the job done. One reason I'd like to change it though is because it appears to take a few hundred milliseconds to execute the verify command on a file. I don't need to verify the certificate I'm just trying to see if a digital signature exists on the file.

So in short, is there a simple way to check if a digital signature exists - without trying to verify it?

Was it helpful?

Solution

I came up with a pretty decent solution using the "Get-AuthenticodeSignature" powershell command. I found this site that explains how to use powershell commands in c#. This way I don't need to spawn several processes, and it's pretty quick.

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);
            }
}

OTHER TIPS

If you want to do this for .NET assemblies, you can do this:

        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.
        }

The X509Certificate class has some static methods that may also be of use (e.g. CreateFromSignedFile), but I am not as familiar with them. This is method we use to double check that a digital signature has been applied by our internal tools.

First of all, signtool works only with PE files. For other file types signing can be done using either wrapping signature or embedded signature or detached signature.

Wrapping signature changes the actual file making it unreadable by those applications that are usually used to read it. Eg. if you create a wrapping signature on PDF, no PDF tool will be able to read the file until the signature is removed.

Some file formats support embedded signatures right in their format (EXE files and Authenticode format are the example). There you can embed the signature into the file and other applications are still able to read it. But this is format-specific and not many formats support this.

Finally detached signatures are kept separately from the file. I.e. if you have a file a.txt, you create a detached signature and put it into, for example, a.txt.pkcs7detached.

As you see, the detached signatures are optimal for your task. And in this case you have a list of .pkcs7detached files so you can check - if the file has no corresponding .pkcs7detached file with a signature, you create a new signature.

All of the above signature types are supported by PKIBlackbox package of our SecureBlackbox product.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top