在 C# 中验证数字签名

verifying digital signature in c#

我有一个签名的 "DLL" 文件,我想在 运行 时间内验证他的数字签名 ("Before I'm loading it")

我的代码中嵌入了证书的 public 密钥, 有没有办法从数字签名中获取 "message digest" ?或其他验证文件未被操纵的方法?

我不想检查证书的 "CA" 和其他属性,因为恶意用户可以创建具有相同属性的证书

*注意我也不想使用 SignTool :)

CryptoAPI 和 p/invoke 有一些工作(我不知道如何使用 .NET 提取验证码签名)。这是我在评论中的意思的代码示例:

using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Security.Cryptography.Pkcs;

namespace CLRSignatures {
    class Program {
        static void Main(string[] args) {
            IntPtr phCertStore = IntPtr.Zero;
            IntPtr phMsg = IntPtr.Zero;
            IntPtr ppvContext = IntPtr.Zero;
            int pdwMsgAndCertEncodingType = 0;
            int pdwContentType = 0;
            int pdwFormatType = 0;
            if (!Crypt32.CryptQueryObject(
                Wincrypt.CERT_QUERY_OBJECT_FILE,
                args[0],
                Wincrypt.CERT_QUERY_CONTENT_FLAG_ALL,
                Wincrypt.CERT_QUERY_FORMAT_FLAG_ALL,
                0,
                ref pdwMsgAndCertEncodingType,
                ref pdwContentType,
                ref pdwFormatType,
                ref phCertStore,
                ref phMsg,
                ref ppvContext
            )) {
                Console.WriteLine((new Win32Exception(Marshal.GetLastWin32Error())).Message);
                return;
            }
            int pcbData = 0;
            if (!Crypt32.CryptMsgGetParam(phMsg, Wincrypt.CMSG_ENCODED_MESSAGE, 0, null, ref pcbData)) {
                Console.WriteLine((new Win32Exception(Marshal.GetLastWin32Error())).Message);
                return;
            }
            byte[] pvData = new byte[pcbData];
            Crypt32.CryptMsgGetParam(phMsg, Wincrypt.CMSG_ENCODED_MESSAGE, 0, pvData, ref pcbData);
            var signedCms = new SignedCms();
            signedCms.Decode(pvData);
            try {
                signedCms.CheckSignature(false);
                Console.WriteLine("Signature check passed");
            } catch (Exception e) {
                Console.WriteLine(e.Message);
            } finally {
                Crypt32.CryptMsgClose(phMsg);
                Crypt32.CertCloseStore(phCertStore, 0);
            }
        }
    }
    static class Wincrypt {
        // source type
        public const int CERT_QUERY_OBJECT_FILE = 1;
        // object type
        const int CERT_QUERY_CONTENT_CERT = 1;
        const int CERT_QUERY_CONTENT_CTL = 2;
        const int CERT_QUERY_CONTENT_CRL = 3;
        const int CERT_QUERY_CONTENT_SERIALIZED_STORE = 4;
        const int CERT_QUERY_CONTENT_SERIALIZED_CERT = 5;
        const int CERT_QUERY_CONTENT_SERIALIZED_CTL = 6;
        const int CERT_QUERY_CONTENT_SERIALIZED_CRL = 7;
        const int CERT_QUERY_CONTENT_PKCS7_SIGNED = 8;
        const int CERT_QUERY_CONTENT_PKCS7_UNSIGNED = 9;
        const int CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED = 10;
        const int CERT_QUERY_CONTENT_PKCS10 = 11;
        const int CERT_QUERY_CONTENT_PFX = 12;
        const int CERT_QUERY_CONTENT_CERT_PAIR = 13;

        const int CERT_QUERY_CONTENT_FLAG_CERT = (1 << CERT_QUERY_CONTENT_CERT);
        const int CERT_QUERY_CONTENT_FLAG_CTL = (1 << CERT_QUERY_CONTENT_CTL);
        const int CERT_QUERY_CONTENT_FLAG_CRL = (1 << CERT_QUERY_CONTENT_CRL);
        const int CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE = (1 << CERT_QUERY_CONTENT_SERIALIZED_STORE);
        const int CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT = (1 << CERT_QUERY_CONTENT_SERIALIZED_CERT);
        const int CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL = (1 << CERT_QUERY_CONTENT_SERIALIZED_CTL);
        const int CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL = (1 << CERT_QUERY_CONTENT_SERIALIZED_CRL);
        const int CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED = (1 << CERT_QUERY_CONTENT_PKCS7_SIGNED);
        const int CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED = (1 << CERT_QUERY_CONTENT_PKCS7_UNSIGNED);
        const int CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED = (1 << CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED);
        const int CERT_QUERY_CONTENT_FLAG_PKCS10 = (1 << CERT_QUERY_CONTENT_PKCS10);
        const int CERT_QUERY_CONTENT_FLAG_PFX = (1 << CERT_QUERY_CONTENT_PFX);
        const int CERT_QUERY_CONTENT_FLAG_CERT_PAIR = (1 << CERT_QUERY_CONTENT_CERT_PAIR);
        public const int CERT_QUERY_CONTENT_FLAG_ALL =
            CERT_QUERY_CONTENT_FLAG_CERT |
            CERT_QUERY_CONTENT_FLAG_CTL |
            CERT_QUERY_CONTENT_FLAG_CRL |
            CERT_QUERY_CONTENT_FLAG_SERIALIZED_STORE |
            CERT_QUERY_CONTENT_FLAG_SERIALIZED_CERT |
            CERT_QUERY_CONTENT_FLAG_SERIALIZED_CTL |
            CERT_QUERY_CONTENT_FLAG_SERIALIZED_CRL |
            CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED |
            CERT_QUERY_CONTENT_FLAG_PKCS7_UNSIGNED |
            CERT_QUERY_CONTENT_FLAG_PKCS7_SIGNED_EMBED |
            CERT_QUERY_CONTENT_FLAG_PKCS10 |
            CERT_QUERY_CONTENT_FLAG_PFX |
            CERT_QUERY_CONTENT_FLAG_CERT_PAIR;

        // format type
        const int CERT_QUERY_FORMAT_BINARY = 1;
        const int CERT_QUERY_FORMAT_BASE64_ENCODED = 2;
        const int CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED = 3;
        const int CERT_QUERY_FORMAT_FLAG_BINARY = 1 << CERT_QUERY_FORMAT_BINARY;
        const int CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED = 1 << CERT_QUERY_FORMAT_BASE64_ENCODED;
        const int CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED = 1 << CERT_QUERY_FORMAT_ASN_ASCII_HEX_ENCODED;
        public const int CERT_QUERY_FORMAT_FLAG_ALL =
            CERT_QUERY_FORMAT_FLAG_BINARY |
            CERT_QUERY_FORMAT_FLAG_BASE64_ENCODED |
            CERT_QUERY_FORMAT_FLAG_ASN_ASCII_HEX_ENCODED;

        public const int CMSG_ENCODED_MESSAGE = 29;

    }
    static class Crypt32 {

        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptQueryObject(
            int dwObjectType,
            [MarshalAs(UnmanagedType.LPWStr)]
            string pvObject,
            int dwExpectedContentTypeFlags,
            int dwExpectedFormatTypeFlags,
            int dwFlags,
            ref int pdwMsgAndCertEncodingType,
            ref int pdwContentType,
            ref int pdwFormatType,
            ref IntPtr phCertStore,
            ref IntPtr phMsg,
            ref IntPtr ppvContext
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptMsgGetParam(
            IntPtr hCryptMsg,
            int dwParamType,
            int dwIndex,
            byte[] pvData,
            ref int pcbData
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CryptMsgClose(
            IntPtr hCryptMsg
        );
        [DllImport("crypt32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern bool CertCloseStore(
            IntPtr hCertStore,
            int dwFlags
        );
    }
}

p.s。请注意,您必须引用 System.Security 程序集。 args[0] 接收 DLL 文件的路径。