The problem:
Using keys contained in an X509 certificate for encryption, implemented in a .Net Standard 2.0 class library, doesn't work if that class library is used by a .Net Core 2.2 application. Or at least *I* cannot get it to work, which is the same thing for me.
I'm not trying to re-invent SSL, what we want to do is encrypt data in a file that is to be sent to us, using anything from 'usb stick by sneaker mail' on up. They use our public key to encrypt, and we decrypt using our private key.
I condensed the problem into a test solution with 3 projects which I can make available, if anyone would want it:
- Net Standard 2.0 class library containing the cryptographic functions
- Windows Forms app, framework 4.7.2: can use the crypto functions, no problem.
- Net Core 2.2 web app: cannot use the crypto functions.
What happens?
The Net Std DLL reads an X509 certificate with the intent to use its keys to asymetrically encrypt a file. It contains simple Encrypt en Decrypt functions, these automatically use the private key when is available (i.e. running here), otherwise the public key if it is running at a client.
Simplified code:
X509Store my = new X509Store(StoreName.My, StoreLocation.LocalMachine); my.Open(OpenFlags.ReadOnly); X509Certificate2Collection collection = my.Certificates.Find(X509FindType.FindBySubjectName, CertificateName, true); _certificate = collection[0]; // somewhere else RSACryptoServiceProvider csp = (RSACryptoServiceProvider)_certificate.PrivateKey; // or RSACryptoServiceProvider csp = (RSACryptoServiceProvider)_certificate.PublicKey.Key; // Also tried with RSACryptoServiceProvider csp = (RSACryptoServiceProvider)_certificate.GetRSAPrivateKey(); RSACryptoServiceProvider csp = (RSACryptoServiceProvider)_certificate.GetRSAPublicKey();
This works fine in the Windows Forms application under 'Classic' framework 4.7.2.
But when the same library is called by the Net Core web app, running in IIS Express with a Core 2.2 runtime, on the same machine, using the same certificate, it balks out. The returned RSA key is a RSACng class.
InvalidCastException: Unable to cast object of type 'System.Security.Cryptography.RSACng' to type 'System.Security.Cryptography.RSACryptoServiceProvider'.
But .Net Standard doesn't *know* RSACng, so I can't even try to convert or re-create it from code.