“密钥不存在”异常抛出。我究竟做错了什么?

时间:2013-10-25 18:59:12

标签: c# exception encryption rsacryptoserviceprovider

我有以下测试,它使用System.Security.Cryptograph.RSACryptoServiceProvider隔离了我遇到的问题。问题是r.Decrypt抛出异常“密钥不存在”。如果我使用privateKeyXml进行加密和解密(而不是在解密时使用publicKeyXml),那么它按预期工作。当然我不想共享私钥,我需要能够使用公钥解密。   有谁看到我在这里做错了什么?

    [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);
    }

1 个答案:

答案 0 :(得分:2)

您正在使用"私钥加密/公钥解密"。我正在一个项目中工作,在这个项目中我们需要这样做。我知道有很多关于此的讨论,但我会继续解释如何做到这一点。我认为有很多问题可以解释我们何时应该使用"签署/验证"或者"公钥加密/私钥解密"或不。

首先,我也得到了与你相同的解决方案,但它没有工作,我测试了很多CspParameters选项。我认为它应该有效,但它没有!

所以,我的最终解决方案是使用BouncyCastle库:

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));