Best way to initiate RSACryptoServiceProvider from x509Certificate2?
Asked Answered
S

3

36

What is the best way to initate a new RSACryptoServiceProvider object from an X509Certificate2 I pulled out of a key store? The certificate is associated with both public (for encryption) and private (for decryption) keys.

I'm current using the FromXmlString method but there must be a better way.

Thanks

Slantwise answered 3/5, 2011 at 16:49 Comment(1)
Please consider changing the accepted answer to Rosdi Kasim's. The currently accepted answer is now very out of date and unreliable.Brainsick
G
52

Note: While this is the accepted answer and was valid back in 2011, this code won't work now under .NET Core. See this answer if you are using .NET Framework 4.6+, or .NET Core / .NET.

RSACryptoServiceProvider publicKeyProvider = 
    (RSACryptoServiceProvider)certificate.PublicKey.Key;

and

RSACryptoServiceProvider privateKeyProvider = 
    (RSACryptoServiceProvider)certificate.PrivateKey;

The key property on the public or private key property of the certificate is of type AsymmetricAlgorithm.

Goodly answered 3/5, 2011 at 16:58 Comment(8)
Thanks blowdart, worked like a charm. Maybe I should buy your book.Slantwise
Note: should be certificate.PrivateKey; not certificate.PrivateKey.Key;Slantwise
Great answer, short and sweet. Are the non-RSA providers just irrelevant? Presumably there's a reason why these properties are AsymmetricAlgorithm, and no guarantee their runtime type will actually be RSACryptoServiceProvider..?Kyliekylila
Well Elliptic Curve is also asymmetric, but there's no real concept of keys. And of course a base class makes for expandability should someone come out with something greater.Goodly
I'll buy his book if he covers RSA keys, import exports. I gave up reading and writing ASN.1 public keys formatted as SubjectPublicKeyInfo. Went to Bouncy Castle and am 99% of the way there. (PS you working on AntiXSS on codeplex? When is the next version?)Diestock
Know what's funny? Exposing the PrivateKey in public environment is a bad security practice, especially on the Cloud servers. :-/Sundin
doesnt work 'System.InvalidCastException: 'Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.''Dejadeject
I'm getting error "Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'." in .NET Core 3.1Matthaus
M
46

The recommended way is to use RSA base class and call certificate.GetRSAPrivateKey().

RSA publicKeyProvider = certificate.GetRSAPrivateKey();

Since .NET 4.6, casting to RSACryptoServiceProvider as suggested by @blowdart is no longer recommended. This is even more an issue now since there are several versions of .NET (such as .NET Core).

By casting to RSACryptoServiceProvider that way, there is a good chance you might get this cast exception (depending on the platform and libraries used):

Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'

The reason is the actual implementation could be different from each platform, on Windows RSACng is used.

Here is a link that describes this issue (look for answer by Jeremy Barton).

Miserable answered 11/4, 2018 at 14:25 Comment(1)
I was able to move forward with this approach.Herrmann
C
9

Blowdart's answer is indeed correct. However, for clarity I should point out that if you want your RSACryptoServiceProvider instance to contain both the public and private keys of the X509 certificate (assuming the certificate does have a private key). Check the certificate's HasPrivateKey property.

RSACryptoServiceProvider rsa;
if (cert.HasPrivateKey)
    rsa = (RSACryptoServiceProvider)cert.PrivateKey;
else
    rsa = (RSACryptoServiceProvider)cert.PublicKey.Key;

In the case of RSA when only the public key is present the RSA Parameters will be only Exponent and Modulus, all others will be null; If on the other hand the private key is present the RSA Parameters will contain D, DP, DQ, Exponent, InverseQ, Modulus, P and Q.

Creolized answered 23/5, 2011 at 5:15 Comment(2)
(RSACryptoServiceProvider)(c.HasPrivateKey ? c.PrivateKey : c.PublicKey.Key); However: I wouldn't ever do this. I'd only load the private key when I intended to use the provider for something that requires it - and then of course it's no help just loading the public key instead.Kyliekylila
Dag is correct, but to clarify... I either want to decrypt with the private key, or encrypt with the public key. There's no situation where I want just whatever might be available.Knott

© 2022 - 2024 — McMap. All rights reserved.