"Key does not exist" exception thrown. What am I doing wrong?
Asked Answered
K

1

7

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);
    }
Keciakeck answered 25/10, 2013 at 18:59 Comment(6)
possible duplicate of how to decrypt an encrypted text using RSACryptoServiceProvider?Sinew
Don't forget how asymmetric encryption works: you always encrypt with the public key and decrypt with the private key.Sinew
yep, this is a dupe. thanksKeciakeck
What I really want to do is use the private key to sign the document such that the public key can be used validate where it came from.Keciakeck
It looks like RSACryptoServiceProvider SignData/CheckData are what I should have been using. Thanks.Keciakeck
For those who came from Google. This code example signs and verifies data: learn.microsoft.com/en-us/dotnet/api/…Medulla
M
2

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));
Mcminn answered 2/3, 2016 at 17:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.