MailMessage.Sign(SignatureHashAlgorithm.SHA256, signer) error

+1 vote
asked Feb 18, 2010 by Daniel Spurny (400 points)
edited Mar 2, 2010

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
answered Mar 2, 2010 by Lukas Pokorny (128,250 points)
edited Mar 2, 2010
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
answered Feb 18, 2010 by Lukas Pokorny (128,250 points)
edited Feb 18, 2010

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);
    		X509Certificate2Collection certificates = store.Certificates.Find(X509FindType.FindBySubjectDistinguishedName, subjectDN, true);
    		X509Certificate2 certificate = certificates[0];

    		// 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.

commented Feb 23, 2010 by Daniel Spurny (400 points)
I'am so sorry, but i'am ill. Ill try it maybye tomorrow.
commented Feb 24, 2010 by Daniel Spurny (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
commented Feb 25, 2010 by Lukas Pokorny (128,250 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.