+1 vote
by (400 points)
edited

I have problem on ms windows server 2003 with hotfix KB 938397. I try sign with certificate which is in old sha1 format. If i sign with SHA1 everything go ok. But if i try sign with SHA256 it produce exception with message "Unable to access the private key (0x80092004)". Where can be problem. If i try it on my MS Vista it works OK.

Applies to: Rebex Secure Mail

2 Answers

0 votes
by (134k points)
edited
 
Best answer

It turned out you were using Certificate(byte[] data) to initialize his instance of Rebex.Security.Certificates.Certificate. Although this works fine when SHA-1 or MD5 signatures are used, it apparently doesn't work when one of SHA-2 algorithms (SHA-256, SHA-384 or SHA-512) is used.

The reason for this is that different CryptoAPI calls have to be done for SHA-2 because a different CryptoAPI provider than the one associated with the certificate's provate key has to be used.

We might try to address this in one of the future releases. In the meantime, if you need to use SHA-2, please make sure to initialize the Certificate class using one of the following methods:

  1. Acquire it using the CertificateStore class.
  2. Load it from a .pfx/.p12 file using Certificate.LoadPfx method.
  3. Use Certificate(IntPtr handle) constructor (in the next release).
0 votes
by (134k points)
edited

Windows Server 2003 with KB938397 hotfix is not sufficiently tested platform and we are not entirely sure whether the hotfix is supposed to make signature generation work - there is a ver similar KB968730 hotfix that is newer and addresses a similar problem, so installing it first might be a good idea.

To help us in analyzing this, could you please run the following program and let us know what output it displays?

using System;
using System.Text;
using System.Security.Cryptography;
using System.Security.Cryptography.Pkcs;
using System.Security.Cryptography.X509Certificates;

namespace Rebex.Support
{
    class CertificateInfo
    {
    	static void Main()
    	{
    		string subjectDN = "cn=AliceRSA"; // replace this with the actual certificate subject DN

    		// find the certificate
    		X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser);
    		store.Open(OpenFlags.ReadOnly);
    		X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, subjectDN, true);
    		X509Certificate2 certificate = certificates[0];
    		store.Close();

    		// display information about the private key
    		RSACryptoServiceProvider rsa = (RSACryptoServiceProvider)certificate.PrivateKey;
    		CspKeyContainerInfo info = rsa.CspKeyContainerInfo;
    		Console.WriteLine("Accessible: {0}", info.Accessible);
    		Console.WriteLine("HardwareDevice: {0}", info.HardwareDevice);
    		Console.WriteLine("KeyContainerName: {0}", info.KeyContainerName);
    		Console.WriteLine("KeyNumber: {0}", info.KeyNumber);
    		Console.WriteLine("MachineKeyStore: {0}", info.MachineKeyStore);
    		Console.WriteLine("Protected: {0}", info.Protected);
    		Console.WriteLine("ProviderName: {0}", info.ProviderName);
    		Console.WriteLine("ProviderType: {0}", info.ProviderType);
    		Console.WriteLine("UniqueKeyContainerName: {0}", info.UniqueKeyContainerName);
    	}
    }
}

We will try to test this ourselves as well in the next few days.

by (400 points)
I'am so sorry, but i'am ill. Ill try it maybye tomorrow.
by (400 points)
Result from your code: Accessible: True HardwareDevice: False KeyContainerName: {CFCFBE30-6919-48E1-B96B-671826A89927} KeyNumber: Exchange MachineKeyStore: False Protected: False ProviderName: Microsoft Enhanced Cryptographic Provider v1.0 ProviderType: 1 UniqueKeyContainerName: 56e8c5d2dd4118ee7b9a885912117c35_131747bf-ce21-4b0c-baaf-f2fdacc6f8ef
by (134k points)
Thanks! Nothing extraordinary in there. We modified our code to use a different approach for accessing private keys. I will send you a link to the current build shortly to our e-mail address.
...