This project has moved. For the latest updates, please go here.

CryptoConfig2

Jan 25, 2011 at 5:41 AM

I'm trying to get RSA-SHA256 to work with the SignedXml framework on W2K8R2 / .NET 3.5.1 using CLR Security June 2010 Release.
The two assemblies are installed in the GAC, and the two machine.config files have been updated.

reference.DigestMethod="http://www.w3.org/2001/04/xmlenc#sha256"
signedXml.SignedInfo.SignatureMethod="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"

results in:

System.Security.Cryptography.CryptographicException: SignatureDescription could not be created for the signature algorithm supplied.
at System.Security.Cryptography.Xml.SignedXml.ComputeSignature()

To test whether the registration of the algorithm extension is correct I compared.

            object algo1=CryptoConfig.CreateFromName("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
            object algo2=CryptoConfig2.CreateFromName("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");

algo1 is null while algo2 returns the correct descriptor.

What am I doing wrong?

 

Coordinator
Feb 2, 2011 at 10:55 PM

There are a couple of things to check

  1. Make sure you updated both the 32 and 64 bit machine.config
  2. Make sure the machine.config entries refer to the correct version fo Security.Cryptography.winmd - the version number has changed a few times, so the comment in the code refers to v1.1, while the current version is v1.6.
Feb 5, 2011 at 7:20 PM

Yes, I followed the instructions without checking the assembly version and had indeed configured the wrong version number in the machine.config.
After the change the SignedXml in both .NET 3.5.1 and .NET 4 finds the right SignatureDescription, and got me to the next stage.

.NET 4.0 returns

A first chance exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
System.Security.Cryptography.CryptographicException: Invalid algorithm specified. at System.Security.Cryptography.CryptographicException.ThrowCryptographicException(Int32 hr) at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 cbHash, ObjectHandleOnStack retSignature) at System.Security.Cryptography.Utils.SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash) at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, String str) at System.Security.Cryptography.Xml.SignedXml.ComputeSignature()

and V3.5.1

A first chance exception of type 'System.Security.Cryptography.CryptographicException' occurred in mscorlib.dll
System.Security.Cryptography.CryptographicException: Invalid algorithm specified.
 at System.Security.Cryptography.CryptographicException.ThrowCryptogaphicException(Int32 hr)
 at System.Security.Cryptography.Utils._SignValue(SafeKeyHandle hKey, Int32 keyNumber, Int32 calgKey, Int32 calgHash, Byte[] hash, Int32 dwFlags)
 at System.Security.Cryptography.RSACryptoServiceProvider.SignHash(Byte[] rgbHash, String str)
 at System.Security.Cryptography.Xml.SignedXml.ComputeSignature()

As long as the error messages change I'm making progress.
Do you have some words of wisdom to get past this hurdle?

Coordinator
Feb 8, 2011 at 6:08 PM

What OS are you on?  Those errors look like the underlying CAPI provider does not support using SHA-2 hashes.

Feb 8, 2011 at 6:24 PM

Hi Shawn,

We are on Windows 2008 R2, that should have the most recent version of the crypto APIs.

When doing a rsa.SignHash(hashBytes,”SHA256”) we run into the same error.

Is does the CodePlex assembly Security.Cryptography extend the implementation of the RsaCryptoServiceProvider, or is this an unrelated operating system level configuration problem?

n Douwe

From: shawnfa [email removed]
Sent: Tuesday, February 08, 2011 13:08
To: Douwe Tolsma
Subject: Re: CryptoConfig2 [clrsecurity:243156]

From: shawnfa

What OS are you on? Those errors look like the underlying CAPI provider does not support using SHA-2 hashes.

Coordinator
Feb 9, 2011 at 2:34 AM

The CodePlex library does not extend RSA at all - it just passes through to the existing platform implementation.

Feb 10, 2011 at 5:51 PM
Edited Feb 10, 2011 at 7:19 PM

Shawn,

I found the following information in http://social.msdn.microsoft.com/Forums/en-US/Geneva/thread/35c10fe5-9693-4f3a-9c5c-8afbb423ee95 

For those who were unable to get this problem resolved using Phil Bolduc's solution...

I was having the same problem, and in reading some known issues with the WIF Samples, it seemed that there is a need to run this function in both 64bit and 32 bit mode, as the registry keys injected by this routine seem to be bound to the platform binary.

The solution is to compile both a 64bit executable and a 32bit executable, and run each of them once.
If you want to check that the OIDs have been registered successfully, check the following registry hives:
  -  32bit  -  HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo
  -  64bit  -  HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Cryptography\OID\EncodingType 0\CryptDllFindOIDInfo

each should contain the 3 OIDs which represent the 3 new SHA2 algorithms
  -  (SHA256) - "2.16.840.1.101.3.4.2.1!1"
  -  (SHA384) - "2.16.840.1.101.3.4.2.2!1"
  -  (SHA512) - "2.16.840.1.101.3.4.2.3!1"


The solution suggests to call Oid2.RegisterSha2OidInformationForRsa(); and I checked the source code of the method which excludes windows 2008 R2. I modified the code to make it do the registration for windows 2008 and did successfully get the 32bit keys registered. However, The 64 bit version wouldn't compile because mscorlib.dll "targets a different processor. Any suggestion on how to register the 64 bit keys?

Come back to the beginning, will registering the 64bit keys resolve the problem? 

Coordinator
Feb 11, 2011 at 12:51 AM

When building 64 bit, make sure that you're referencing the 64 bit version of mscorlib.dll (in Framework64, rather than Framework).   If the OS doesn't have the OIDs in place, then yes, updating them for both 32 and 64 bit should do the trick for you.

Mar 4, 2011 at 8:01 AM

Hi,

I'm experiencing the same problem, getting a "Invalid algorithm specified." when trying to sign with SHA-256 using SignHash. I'm also getting the same error when trying to use SignedXml and setting SignedInfo.SignatureMethod to "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".

I'm running Windows 7 64 bit and have tested with both .NET 3.5 SP1 and .NET 4. I have edited the machine.config in:

C:\Windows\Microsoft.NET\Framework64\v2.0.50727\CONFIG
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\Config
C:\Windows\Microsoft.NET\Framework\v2.0.50727\CONFIG
C:\Windows\Microsoft.NET\Framework\v4.0.30319\Config

and added:

  <mscorlib>
    <cryptographySettings>
      <cryptoNameMapping>
        <cryptoClasses>
          <cryptoClass RSASHA256SignatureDescription="Security.Cryptography.RSAPKCS1SHA256SignatureDescription, Security.Cryptography, Version=1.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
        </cryptoClasses>
        <nameEntry name="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" class="RSASHA256SignatureDescription" />
      </cryptoNameMapping>
    </cryptographySettings>
  </mscorlib>



I have also installed the Security.Cryptography.dll in the GAC.

Furthermore, I have also registered the OIDs using Oid2.RegisterSha2OidInformationForRsa(); after modifying it to accept Windows 7.

The code I'm using is:

X509Certificate2 cert = new X509Certificate2("test.pfx", "test");
RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
byte[] signature = rsa.SignHash(Encoding.UTF8.GetBytes("message"), "SHA256");

If i switch to SHA1 as algorithm, the code works.

Any help is appreciated

Mar 4, 2011 at 1:49 PM
Edited Mar 4, 2011 at 1:51 PM

You are on the right track, one detail missing
The rsa object is linked to the wrong cryptoservice provider.

To create an RSA-SHA256 signature you will need to force the Microsoft Enhanced RSA and AES Cryptographic Provider to be used.
On my Windows 2008R2 machine this is identified by type 24. Windows 7 will most likely use the same value.

My recommendation is to research something like below.

     
          byte[] privateKeyBlob;
          X509Certificate2 cert = new X509Certificate2("test.pfx", "test");
          try {
            privateKeyBlob=cert.ExportCspBlob(true);
          } catch {
            throw new ApplicationException("Private key fails to export");
          }
          // To use the RSA-SHA256 the CryptoAPI needs to select a special CSP: Microsoft Enhanced RSA and AES Cryptographic Provider
          // By reinstantiating a CSP of type 24 we ensure that we get the right CSP.
          CspParameters cp=new CspParameters(24);
          cert=new RSACryptoServiceProvider(cp);
          cert.ImportCspBlob(privateKeyBlob);
          byte[] signature = rsa.SignHash(Encoding.UTF8.GetBytes("message"), "SHA256");
Mar 9, 2011 at 1:12 PM

Thank you, it works!

As it turns out, I don't need the CLR security package at all, I was just using the wrong crypto service provider.

When I was using the code I'm getting the "Microsoft Strong Cryptographic Provider" (type 1):

X509Certificate2 cert = new X509Certificate2("test.pfx", "test");
RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
byte[] signature = rsa.SignData(Encoding.UTF8.GetBytes("message"), "SHA256");

However, when using the following code i'm getting the "Microsoft Enhanced RSA and AES Cryptographic Provider" (type 24):

X509Certificate2 cert = new X509Certificate2("test.pfx", "test", X509KeyStorageFlags.Exportable);
RSACryptoServiceProvider rsa = cert.PrivateKey as RSACryptoServiceProvider;
byte[] privateKeyBlob = rsa.ExportCspBlob(true);
RSACryptoServiceProvider rsa2 = new RSACryptoServiceProvider();
rsa2.ImportCspBlob(privateKeyBlob);
byte[] signature = rsa2.SignData(Encoding.UTF8.GetBytes("message"), "SHA256");


My conclusion is that when casting the private key of the certificate to a RSACryptoServiceProvider, the provider type gets set to 1, but when creating a RSACryptoServiceProvider with the constructor, the type gets set to 24.
According to http://blogs.msdn.com/b/alejacma/archive/2009/04/30/default-provider-type-for-cspparameters-has-changed.aspx, default is type 24 from .NET 3.5 SP1 and above for OS's supporting it.

Is there a more elegant way of creating a signature with SHA256 by using a certificate without the need to create two RSACryptoServiceProviders as in my example above?

Oct 5, 2012 at 1:37 PM

Descartes2,

Can you let  me know if you got this working in .Net 3.5 with Cryptoconfig2 and Signedxml.signedinfo.signaturemethod as SHA 256.? I have updated the configs and the Security.Cryptography.dll to my .Net 3.5 Project and I am not sure of registering the OIds as desphyxia mentioned??  has WS2k8 R2 as OS 64 bit.?? Let me know if this works in 3.5, I have this working in 4.0.

 

Desphyxia,

           You mentioned it works for you ??wanted to know if it is 3.5 or 4.0. I have this working in .Net 4.0 without the CLS package (Secruity.Cryptography.dll) as I am Crytoconfig.Addalgorithm to add my signature defnition at runtime in .Net 4.0 application.?? Also wanted to know the correct version of  " <cryptoClass RSASHA256SignatureDescription="Security.Cryptography.RSAPKCS1SHA256SignatureDescription, Security.Cryptography, Version=1.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</cryptoClasses> " is it still 1.6.0.0 as the latest?

 

Thanks and appreciate your earnest response

Oct 5, 2012 at 2:02 PM

The explicit type 24 construction method works on both .NET 3.5 as well as on .NET 4.0 on the x64 bit OS Windows 2008R2.

Please note that you need to find the corresponding machine.config and add the

mscorlib/cryptographySettings/cryptoNameMapping/cryptoClasses/cryptoClass/nameEntry element.

To get it running in all configurations you may need to make this addition four times

C:\WINDOWS \Microsoft.NET\Framework64\v4.0.30319\Config\machine.config

C:\WINDOWS \Microsoft.NET\Framework\v4.0.30319\Config\machine.config

C:\WINDOWS\Microsoft.NET\Framework64\v2.0.50727\CONFIG\machine.config

C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\CONFIG\machine.config

It is my understanding the v3.5 uses the v2.0.50727 framework configuration files.