Verifying digital signature in C #

I have a signed "DLL" file that I want to verify its digital signature at runtime ("Before loading it")

I have the public key of the certificate embedded in my code. Is there a way to get the "message digest" from the digital signature? or is there another way to check the file not being processed?

I don't want to check "CA" and other attributes of the certificate, because a malicious user can create a certificate with the same attributes

* Note. I also don't want the SignTool user :)

+3


source to share


1 answer


There is some work around for CryptoAPI and p / invoke (I don't know how to extract the signature signature using .NET). Here is some sample code that I had in mind in my comment:

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

      



ps note that you need to reference the assembly System.Security

. args[0]

gets the path to the DLL file.

+5


source







All Articles