Reputation: 24480
I have the below test which isolates a problem I'm running into using System.Security.Cryptograph.RSACryptoServiceProvider. The problem is that r.Decrypt is throwing exception "Key does not exist". If I use privateKeyXml for both the encryption and decryption (instead of using publicKeyXml when decrypting) then it works as expected. Of course I do not want to share the private key, I need to be able to decrypt with the public key. Does anyone see what I'm doing wrong here?
[Fact]
public void BasicEncryptDecrypt()
{
var cspParameters = new CspParameters() { Flags = CspProviderFlags.CreateEphemeralKey | CspProviderFlags.NoPrompt };
string privateKeyXml = null;
string publicKeyXml = null;
using(var r = new RSACryptoServiceProvider(2048, cspParameters)){
r.PersistKeyInCsp = false;
privateKeyXml = r.ToXmlString(true);
publicKeyXml = r.ToXmlString(false);
}
byte[] encrypted = null;
string decrypted = null;
using (var r = new RSACryptoServiceProvider(2048, cspParameters))
{
r.FromXmlString(privateKeyXml);
encrypted = r.Encrypt(Encoding.UTF8.GetBytes("foobar"), false);
}
using (var r = new RSACryptoServiceProvider(2048, cspParameters))
{
r.FromXmlString(publicKeyXml);
decrypted = Encoding.UTF8.GetString(r.Decrypt(encrypted, false));
}
Assert.Equal("foobar", decrypted);
}
Upvotes: 7
Views: 3801
Reputation: 1316
You are using a "private key encryption / public key decryption". I'm working in a project where there's a specific context where we need do it. I know that there is a lot of discussions about this, but I will go on to explain how to do it. I think there are a lot of questions where it explains when we should use "sign/verify" or "public key encryption / private key decryption" or not.
First of all, I also got the same solution as you but it didn't work, I tested a lot of CspParameters options. I think it should work, but it doesn't!
So, my final solution was to use the BouncyCastle libraries:
RsaPrivateCrtKeyParameters privateKeyParameters = (RsaPrivateCrtKeyParameters)PrivateKeyFactory.CreateKey(Convert.FromBase64String(prvKey));
AsymmetricKeyParameter publicKeyInfoParameters = PublicKeyFactory.CreateKey(Convert.FromBase64String(pubKey));
byte[] clearData = Encoding.UTF8.GetBytes("...");
string algorithm = "RSA/ECB/PKCS1Padding";
var cipherOne = Org.BouncyCastle.Security.CipherUtilities.GetCipher(algorithm);
cipherOne.Init(true, privateKeyParameters);
byte[] signedData = cipherOne.DoFinal(clearData);
var clientTwo = CipherUtilities.GetCipher(algorithm);
clientTwo.Init(false, publicKeyInfoParameters);
var clearDataTwo = clientTwo.DoFinal(signedData);
Assert.IsTrue(Convert.ToBase64String(clearData) == Convert.ToBase64String(clearDataTwo));
Upvotes: 2