How to obtain the certificate of the digital signature in the reader?

0

I am working on a application that works with digital signature (authentication and signing of documents) on a WPF project. For requirements I have to use the certificate that is in the card reader, for this I use the code taken from here

The code I use to obtain the certificate is the following:

private X509Certificate2 GetCertificate()
{
    X509Store x509Store = null;
    try
    {
        x509Store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
        x509Store.Open(OpenFlags.ReadOnly | OpenFlags.OpenExistingOnly);
        List<string> containers = GetContainerKey();
        string pubKeyXml = null;
        foreach (string container in containers)
        {
            CspParameters cspParameters = new CspParameters((int)NativeMethods.PROV_RSA_FULL, _providerName, container);
            cspParameters.Flags = CspProviderFlags.UseExistingKey;
            pubKeyXml = null;
            using (RSACryptoServiceProvider rsaProvider = new RSACryptoServiceProvider(cspParameters))
                pubKeyXml = rsaProvider.ToXmlString(false);
            foreach (X509Certificate2 cert in x509Store.Certificates)
            {
                if ((cert.PublicKey.Key.ToXmlString(false) == pubKeyXml) && cert.HasPrivateKey)
                {
                    return cert;
                }
            }
        }
    }
    catch (Exception e)
    {
        return null;
    }
    return null;
}

private static List<string> GetContainerKey()
{
    List<string> containers = new List<string>();
    IntPtr hProv = IntPtr.Zero;
    try
    {
        if (!NativeMethods.CryptAcquireContext(ref hProv, null, _providerName, NativeMethods.PROV_RSA_FULL, NativeMethods.CRYPT_VERIFYCONTEXT))
            throw new Win32Exception(Marshal.GetLastWin32Error());

        uint pcbData = 0;
        uint dwFlags = NativeMethods.CRYPT_FIRST;
        if (!NativeMethods.CryptGetProvParam(hProv, NativeMethods.PP_ENUMCONTAINERS, null, ref pcbData, dwFlags))
            throw new Win32Exception(Marshal.GetLastWin32Error());

        StringBuilder sb = new StringBuilder((int)pcbData + 1);
        while (NativeMethods.CryptGetProvParam(hProv, NativeMethods.PP_ENUMCONTAINERS, sb, ref pcbData, dwFlags))
        {
            containers.Add(sb.ToString());
            dwFlags = NativeMethods.CRYPT_NEXT;
        }

        int err = Marshal.GetLastWin32Error();
        if (err != NativeMethods.ERROR_NO_MORE_ITEMS)
        {
            try
            {
                if (containers.Count > 0)
                    throw new Win32Exception(err);
            }
            catch
            {
                containers = null;
            }
        }
        if (hProv != IntPtr.Zero)
        {
            if (!NativeMethods.CryptReleaseContext(hProv, 0))
                throw new Win32Exception(Marshal.GetLastWin32Error());
            hProv = IntPtr.Zero;
        }
    }
    catch
    {
        if (hProv != IntPtr.Zero)
        {
            if (!NativeMethods.CryptReleaseContext(hProv, 0))
                throw new Win32Exception(Marshal.GetLastWin32Error());
            hProv = IntPtr.Zero;
        }

        throw;
    }
    return containers;
}

private static class NativeMethods
{
    public const uint PROV_RSA_FULL = 0x00000001;
    public const uint CRYPT_VERIFYCONTEXT = 0xF0000000;
    public const uint CRYPT_FIRST = 0x00000001;
    public const uint CRYPT_NEXT = 0x00000002;
    public const uint ERROR_NO_MORE_ITEMS = 0x00000103;
    public const uint PP_ENUMCONTAINERS = 0x00000002;

    [DllImport("advapi32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)]
    public static extern bool CryptAcquireContext(
    ref IntPtr phProv,
    [MarshalAs(UnmanagedType.LPStr)] string pszContainer,
    [MarshalAs(UnmanagedType.LPStr)] string pszProvider,
    uint dwProvType,
    uint dwFlags);

    [DllImport("advapi32.dll", BestFitMapping = false, ThrowOnUnmappableChar = true, SetLastError = true)]
    public static extern bool CryptGetProvParam(
    IntPtr hProv,
    uint dwParam,
    [MarshalAs(UnmanagedType.LPStr)] StringBuilder pbData,
    ref uint pdwDataLen,
    uint dwFlags);

    [DllImport("advapi32.dll", SetLastError = true)]
    public static extern bool CryptReleaseContext(
    IntPtr hProv,
    uint dwFlags);
}

Basically what it does is obtain the public key and then search the certificates stored in the store for the public key that matches. I know it does not work for all types of certificates (as it says in the notes), but it works for certificates with SHA256. Also I need this to work for certificates with SHA1. I have changed the parameters for the csp but I can not get the public key for both types of formats.

Does anyone knows how I can obtain the certificate of the digital signature that is in the reader, (for both, SHA1 and SHA256)?

Thanks!

c#
smartcard
sha1
sha256
x509certificate2
asked on Stack Overflow Dec 1, 2017 by Josh S.M.

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0