whoami
whoami

Reputation: 123

SignedData giving Invalid algorithm specified.exception

I tried to sign and valid my signed data using myCert.pfx file private and public key. But while signing the data I am getting " Invalid algorithm specified." exception

.Net framework we are using is 4.5 and the code is as below

public static void CallMainMethod()
{
    string str = "Sign and verify the data";
    X509Certificate2 certificate = LoadPrivateKey();

    byte[] hashBytes = GetDataHash(str);
    byte[] signature = GetDigitalSignature(hashBytes);
} 

 private static X509Certificate2 LoadPrivateKey()
{
    return new X509Certificate2(@"d:\Keys\myCert.pfx", "Pass#@123");
}

 private static byte[]  GetDataHash(string sampleData)
{
    //choose any hash algorithm
    SHA256Managed managedHash = new SHA256Managed();
    return managedHash.ComputeHash(Encoding.Unicode.GetBytes(sampleData));
}

private static byte[] GetDigitalSignature(byte[] data)
{
    X509Certificate2 certificate = LoadPrivateKey();
    RSACryptoServiceProvider provider = (RSACryptoServiceProvider)certificate.PrivateKey;   
    return provider.SignHash(data, "SHA256");
}

Upvotes: 1

Views: 1376

Answers (2)

bartonjs
bartonjs

Reputation: 33178

While @Crypt32 gave the best answer (upgrade to .NET Framework 4.6 or better and use GetRSAPrivateKey() and the better version of SignData -- it's been out over 4 years at this point), if you really need to stay on net45, your easiest answer is to open the PFX with X509KeyStorageFlags.Exportable and copy the key into a better provider.

return new X509Certificate2(@"d:\Keys\myCert.pfx", "Pass#@123", X509KeyStorageFlags.Exportable);

...

RSA legacyProv = (RSA)certificate.PrivateKey;
RSACryptoServiceProvider provider = new RSACryptoServiceProvider();
provider.ImportParameters(legacyProv.ExportParameters(true));
return provider.SignHash(data, "SHA256");

Upvotes: 0

Crypt32
Crypt32

Reputation: 13974

I believe that legacy RSACryptoServiceProvider doesn't support SHA2 algorithms. Rewrite last method as follows:

private static byte[] GetDigitalSignature(byte[] data)
{
    X509Certificate2 certificate = LoadPrivateKey();
    RSA provider = certificate.GetRSAPrivateKey();   
    return provider.SignHash(data, "SHA256", RSASignaturePadding.Pkcs1);
}

This style is preferred as of .NET Framework 4.6 and above (@bartonjs, please correct me if I'm wrong in regards to .NET version).

Upvotes: 1

Related Questions