2013-10-25 44 views
6

我有下面的測試,它隔離了使用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

可能重複[如何使用的RSACryptoServiceProvider解密加密的文本?](http://stackoverflow.com/questions/6763741/how -crypt-text-using-rsacryptoserviceprovider) –

+3

不要忘記非對稱加密是如何工作的:你總是用公鑰進行加密並用私鑰解密。 –

+0

是的,這是一個騙局。謝謝 –

回答

1

您正在使用「私鑰加密/公鑰解密」。我正在一個項目中有一個特定的環境,我們需要這樣做。我知道有很多這方面的討論,但我會繼續解釋如何去做。我想在解釋什麼時候應該使用「簽名/驗證」或「公鑰加密/私鑰解密」還是有很多問題。

首先,我也得到了與您相同的解決方案,但它沒有奏效,我測試了很多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));