2013-04-28 63 views
1

我在C#下面的代碼:C# - 加密和解密數據使用RSA

主類

X509Certificate2 cert = new X509Certificate2("C:/test.pfx", "hello", X509KeyStorageFlags.Exportable | X509KeyStorageFlags.PersistKeySet); 

      Encryption enc = new Encryption(); 
      string encrypted = enc.Encrypt("hello there", cert); 
      string decrypted = enc.Decrypt(encrypted, cert); 
      Console.WriteLine("Encrypted Text: " + encrypted); 
      Console.WriteLine("Decrypted Text: " + decrypted); 

加密類

public string Encrypt(string plainText, X509Certificate2 cert) 
{ 
    RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key; 
    byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); 
    byte[] encryptedBytes = publicKey.Encrypt(plainBytes, false); 
    string encryptedText = encryptedBytes.ToString(); 
    return encryptedText; 
} 

public string Decrypt(string encryptedText, X509Certificate2 cert) 
{ 
    RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)cert.PrivateKey; 
    byte[] encryptedBytes = Encoding.UTF8.GetBytes(encryptedText); 
    byte[] decryptedBytes = privateKey.Decrypt(encryptedBytes, false); 
    string decryptedText = decryptedBytes.ToString(); 
    return decryptedText; 
} 

正如你所看到的,在主要課程中,我正在導入證書。然後我創建一個Encryption類的實例。然後,我將純文本與證書一起傳遞給Encrypt方法以獲取加密文本。之後,我將加密文本傳遞給Decrypt方法以獲取明文。

我的問題是打印加密文本的結果是系統。[]字節(如果我註釋瞭解密調用)。如果我不註釋解密調用,則會在解密方法中得到加密例外:錯誤數據。

我想encryptedBytes數組沒有正確轉換爲字符串。此外,我不確定我是否正確組建了RSAEncryptionProvider。我該如何解決這個問題?

更新

我解決了一個問題。當從字節數組轉換爲字符串時,我不得不使用Encoding.UTF8.GetString(EncryptedBytes)。現在的問題是解密方法給了我另一個加密異常(他要解密的數據超過了這個128字節模數的最大值)。

有人知道爲什麼會發生這種情況,以及如何解決它?

+1

加密總是二進制數據進行(儘管它可能看起來像你的字符串),並總是產生二進制數據輸出。你爲什麼期待任何字符串? – 2013-04-28 10:26:27

+0

請不要在標題中重複標籤。 – 2013-04-28 10:30:32

+0

@Eugene我想在屏幕上顯示文本,看看它是否真的有效 – Matthew 2013-04-28 10:32:56

回答

2

不要將加密數據視爲字符串。加密算法對二進制數據起作用,並生成不能被解釋爲字符串的二進制數據。認爲UTF-8或任何其他編碼能夠將任何給定的二進制數據塊解釋爲有效字符串是天真的。

在你的情況,如果需要輸出加密數據到控制檯進行調試,繼續與byte[]和轉儲它以十六進制,像這樣:

for (int i = 0; i < data.Length; i++) 
{ 
    Console.Write(data[i].ToString("X2")); 
    Console.Write(" "); 
    if ((i+1) % 16 == 0) Console.WriteLine(); 
} 
+0

但是,如果您想要將來自服務器A(Windows)的加密字節[]數據傳遞到運行在Linux上的另一臺服務器B,您如何使用RSA加密? – Legends 2016-05-01 00:28:38

+0

@Legends您使用的操作系統與加密的工作方式無關。 – 2016-05-01 09:53:49

+0

我想說的是,馬修在評論中這樣說道: >>我想在屏幕上顯示文字,看它是否真的有效<< 所以這是他的意圖,要顯示文字看看是否他的enc/dec函數工作: 但你說二進制數據不能被解釋爲字符串。 這是錯的,還是你的意思是別的?像這樣: 'var cert = getC(); RSACryptoServiceProvider rsa =(RSACryptoServiceProvider)cert.PublicKey.Key; byte [] cipherData = rsa.Encrypt(Encoding.UTF8.GetBytes(plainData),_onlyValidCerts); return Convert.ToBase64String(cipherData);' – Legends 2016-05-01 23:00:41

1

您可以使用Base64格式轉換類型通過變量(encryptedText)參數的替代功能

public string Encrypt(string plainText, X509Certificate2 cert) 
{ 
    RSACryptoServiceProvider publicKey = (RSACryptoServiceProvider)cert.PublicKey.Key; 
    byte[] plainBytes = Encoding.UTF8.GetBytes(plainText); 
    byte[] encryptedBytes = publicKey.Encrypt(plainBytes, false); 
    string encryptedText = Convert.ToBase64String(encryptedBytes); 
    return encryptedText; 
} 

public string Decrypt(string encryptedText, X509Certificate2 cert) 
{ 
    RSACryptoServiceProvider privateKey = (RSACryptoServiceProvider)cert.PrivateKey; 
    byte[] encryptedBytes = Convert.FromBase64String(encryptedText); 
    byte[] decryptedBytes = privateKey.Decrypt(encryptedBytes, false); 
    string decryptedText = Encoding.UTF8.GetString(decryptedBytes); 
    return decryptedText; 
}