2
votes

Creating RSA or RSACryptoServiceProvider object in .Net 4.6 is defaulting KeyExchangeAlgorithm RSA-PKCS1-KeyEx which supports only OaepSHA1 padding.

Getting "Specified padding mode is not valid for this algorithm" on trying to use other padding like "OaepSHA256".

Is there a way to override algorithm in RSA object to an algorithm that supports this padding to make it supportive for all paddings.

enter image description here

UPDATE RSACng works. In my scenario I am using containerkey to store private key in the machine using RSACryptoServiceProvider to retrieve private key when required using containerkey name. As a workaround to use RSACng I am importing properties exporting from RSACryptoServiceProvider object like shown below. Is there a better way to do this?

using (var rsa = new RSACryptoServiceProvider(cspParams))
            {
                using(var rsaCng = new RSACng())
                {
                    rsaCng.ImportParameters(rsa.ExportParameters(true));

                    decryptedResult = rsaCng.Decrypt(encryotedText, RSAEncryptionPadding.OaepSHA256)
                }
            }
1
"in .Net 6.0" - there is no .NET 6.0. Please clarify what platform you're targeting. - Dai
The KeyExchangeAlgorithm property has no real meaning, you should ignore it. But you need to use RSACng, not RSACryptoServiceProvider. - bartonjs
Sorry for the typo its .NET 4.6 - TryingStuff
Thanks RSACng works. In my scenario I am using containerkey to store private key in the machine using RSACryptoServiceProvider to retrieve private key when required using containerkey name. As a workaround to use RSACng I am importing properties exporting from RSACryptoServiceProvider object does it sounds fine. Is there a better way? - TryingStuff
Thanks @Dai RSACng works. Any comments on the workaround provided in update - TryingStuff

1 Answers

3
votes

RSA supports OaepSHA256 in .NET Framework since .NET Framework 4.6 and in .NET Core since 1.0 (as well as OaepSHA1, OaepSHA256, OaepSHA384, OaepSHA512 and the standard for PKCS#1, see the documentation here).

As for support in older versions of .NET Framework - I don't believe it's possible because the Cryptography API treats cryptographic algorithm implementations as opaque black-boxes without much room for extensibility (i.e. you can't really subclass an existing implementation, but you can reimplement your own easily enough). I note this is partly because the API simply wraps Windows' built-in crypto functionality which is opaque anyway (like how System.Drawing wraps GDI without much room for extension there either).

As for the "Specified padding mode is not valid for this algorithm" error - the issue is you're using RSACryptoServiceProvider instead of RSACng. You should prefer the Cryptographic-Next-Generation (Cng) implementations over CryptoServiceProvider implementations, see this article for more details.

If you're targeting .NET Framework 4.6 or later, or .NET Core 1.0 or later, you can use it like so:

using Sytem.Security.Cryptography;

Byte[] inputPlaintext = ...
RSAEncryptionPadding oaepsha256 = RSAEncryptionPadding.OaepSHA256;
using( RSA rsaImpl = new RSACng() )
{
    Byte[] ciphertext = rsaImpl.Encrypt( inputPlaintext, oaepsha256 );
}