2

I have an application running on windows where I want to sign data with any smart card certificate.

Sory for my english, its not my native language. Here is code what I use:

string heslo = "289-Black Joe";
var myStore = new X509Store();
myStore.Open(OpenFlags.ReadOnly);

foreach(X509Certificate2 cert in myStore.Certificates)
{
    if(!cert.HasPrivateKey) continue; // not smartcard for sure
    try
    {
        var rsa = cert.PrivateKey as RSACryptoServiceProvider; // exception here
        if(rsa == null) continue; // not smart card cert again
        if(rsa.CspKeyContainerInfo.HardwareDevice) // sure - smartcard
        {
            signedHash = rsa.SignHash(HashData(heslo), CryptoConfig.MapNameToOID("SHA1"));
            var pom = Encoding.Default.GetString(signedHash);
            myStore.Close();
            return;
        }
    } catch(Exception ex)
    {
        Console.WriteLine(ex);
    }
}
myStore.Close();

The code work when in the project setting in Build->Platform target->Prefer 32-bit is checked. When iterating certificates get to the card certificate it request PIN code to card and then my data are signed. But when the "Prefer 32-bit" is unchecked (thats what I need) the window for request PIN code is skiped becouse cannot get private key of certificate.

I am not really sure why this is happening and I am also not really familiar working with certificates.

  • See : https://en.wikipedia.org/wiki/Secure_Hash_Algorithms (SHA-256 uses 32-bit words where SHA-512 uses 64-bit words). You need to use Sha256. See : https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.sha256?view=netframework-4.8 – jdweng Sep 24 '19 at 12:03
  • Thanks for quick reply. The example code never reach rsa.SignHash method at 64bit option. It will not ask for PIN code to smart card, but at 32bit option it will ask. – Jiří Vrbas Sep 24 '19 at 12:25
  • 2
    @JiříVrbas Probably a smartcard driver problem, i.e. you have only 32bit drivers. I would try `certutil -user -store my` on a 64bit OS to prove it. Certutil should be a 64bit application. It will try to use the keys and do signature/encryption check with them. – pepo Sep 24 '19 at 13:01
  • @pepo when I runned certutil script it also doesn't ask for PIN to card so probably I miss drivers. Thank you. – Jiří Vrbas Sep 24 '19 at 13:28
  • Can you step through code to determine where the error is occurring? I thought the error would be at the MapNameToOID("SHA1"). I would change foreach to var so it would accept any type certificate From : X509Certificate2 cert in myStore.Cert To : var cert in myStore.Cert – jdweng Sep 24 '19 at 13:30
  • you can use certutil in 32/64bit variant for testing! use the SysWow64 folder for the other variant – Paul Bastian Sep 25 '19 at 09:06
  • 1
    @jdweng The hash function has really nothing to do with it. And you can program SHA-256 on a 64 bit platform and SHA-512 on a 32 bit machine without any issue (of course). – Maarten Bodewes Oct 02 '19 at 03:42
  • @jdweng added comment to line where is exception throwen.Exception is "Invalid provider type" but it happens only if "Prefer 32-bit" is checked in project settings. – Jiří Vrbas Oct 02 '19 at 06:58
  • I don't see the comment. See https://stackoverflow.com/questions/22581811/invalid-provider-type-specified-cryptographicexception-when-trying-to-load-pri I've seen a couple of recent postings where updating to Net 4.8 there is issues with 32 bit encryption. Have not found anybody with a solution. – jdweng Oct 02 '19 at 08:54
  • Its happen on line when converting private key to RSACryptoServiceProvider. I dont understand why its happen when "Prefer 32-bit" is checked. The certificate is from smart card. – Jiří Vrbas Oct 02 '19 at 13:35

0 Answers0