验证可执行文件是不是已签名(用于签署该 exe 的signtool)

Posted

技术标签:

【中文标题】验证可执行文件是不是已签名(用于签署该 exe 的signtool)【英文标题】:Verify whether an executable is signed or not (signtool used to sign that exe)验证可执行文件是否已签名(用于签署该 exe 的signtool) 【发布时间】:2011-05-19 18:13:34 【问题描述】:

在我的应用程序中,我需要验证它是否已签名。如果已签名,则继续执行,否则退出应用程序。 signtool 将用于对应用程序进行签名。 是否有任何 C# 代码可以做到这一点?

【问题讨论】:

您使用什么来签署应用程序? 其实我用的是signtool。 【参考方案1】:

这是一个实用的方法:

var signed = IsSigned(@"c:\windows\explorer.exe");
...
public static bool IsSigned(string filePath)

    if (filePath == null)
        throw new ArgumentNullException(nameof(filePath));

    var file = new WINTRUST_FILE_INFO();
    file.cbStruct = Marshal.SizeOf(typeof(WINTRUST_FILE_INFO));
    file.pcwszFilePath = filePath;

    var data = new WINTRUST_DATA();
    data.cbStruct = Marshal.SizeOf(typeof(WINTRUST_DATA));
    data.dwUIChoice = WTD_UI_NONE;
    data.dwUnionChoice = WTD_CHOICE_FILE;
    data.fdwRevocationChecks = WTD_REVOKE_NONE;
    data.pFile = Marshal.AllocHGlobal(file.cbStruct);
    Marshal.StructureToPtr(file, data.pFile, false);

    int hr;
    try
    
        hr = WinVerifyTrust(INVALID_HANDLE_VALUE, WINTRUST_ACTION_GENERIC_VERIFY_V2, ref data);
    
    finally
    
        Marshal.FreeHGlobal(data.pFile);
    
    return hr == 0;


[StructLayoutAttribute(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct WINTRUST_FILE_INFO

    public int cbStruct;
    public string pcwszFilePath;
    public IntPtr hFile;
    public IntPtr pgKnownSubject;


[StructLayoutAttribute(LayoutKind.Sequential)]
private struct WINTRUST_DATA

    public int cbStruct;
    public IntPtr pPolicyCallbackData;
    public IntPtr pSIPClientData;
    public int dwUIChoice;
    public int fdwRevocationChecks;
    public int dwUnionChoice;
    public IntPtr pFile;
    public int dwStateAction;
    public IntPtr hWVTStateData;
    public IntPtr pwszURLReference;
    public int dwProvFlags;
    public int dwUIContext;
    public IntPtr pSignatureSettings;


private const int WTD_UI_NONE = 2;
private const int WTD_REVOKE_NONE = 0;
private const int WTD_CHOICE_FILE = 1;
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private static readonly Guid WINTRUST_ACTION_GENERIC_VERIFY_V2 = new Guid("00AAC56B-CD44-11d0-8CC2-00C04FC295EE");

[DllImport("wintrust.dll")]
private static extern int WinVerifyTrust(IntPtr hwnd, [MarshalAs(UnmanagedType.LPStruct)] Guid pgActionID, ref WINTRUST_DATA pWVTData);

【讨论】:

解决方案非常复杂,我只需要一个真假:exe签名,exe未签名 我认为您没有太多选择。验证码检查不是那么容易。只需复制粘贴代码并调用最后一个函数:internal static uint WinVerifyTrust(string fileName)。返回的 0 表示已签名。 @Anaseh 正如西蒙指出的那样,签名验证不仅仅是真假。您需要确定签名的存在,它的有效性,然后是用于制作签名的证书的有效性,时间戳的有效性和用于签署时间戳的证书。【参考方案2】:
   private bool IsAssemblySigned()
    
        var assembly = Assembly.GetAssembly(GetType());

        var assemblyName = assembly.GetName();
        var key = assemblyName.GetPublicKey();
        return key.Length > 0;
    

【讨论】:

打败我,我打算建议 AssemblyName.GetPublicKey() msdn.microsoft.com/en-us/library/… 感谢您的回答,但是这个解决方案不起作用,因为我没有使用程序集签名,我正在使用 signtool 对应用程序进行签名 是的,signtool 创建 Authenticode 签名,不要与 .NET 强名称密钥签名相混淆。请参阅下面的答案。【参考方案3】:

我建议您使用“CryptUIWizDigitalSign”API。 This link可以作为参考。

【讨论】:

【参考方案4】:
    Try
        Dim objCertificate As New Security.Cryptography.X509Certificates.X509Certificate2(Security.Cryptography.X509Certificates.X509Certificate.CreateFromSignedFile(strFile))
        Return True

    Catch ex As Exception
        Return False
    End Try

【讨论】:

以上是关于验证可执行文件是不是已签名(用于签署该 exe 的signtool)的主要内容,如果未能解决你的问题,请参考以下文章

发布时在 clickonce 应用程序中签署可执行文件

使用 signtool.exe 签署多个文件

每日随笔电子签名 ( 下载 “e 签保“ 应用 | 使用 手机号 + 短信验证码 登录 | 发起签署 | 签名 | 获取签名后的 PDF 文件及出证信息 )

EV 代码签名存在问题

自动化扩展验证 (EV) 代码签名

盲目签署和验证的库或软件是什么?