2013-04-28 38 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; 
}