修改MSDN上的示例,使之可以通过RSA证书文件加密和解密,中间遇到一个小问题。
Q:执行ExportParameters()方法时,回报CryptographicException:该项不适于在指定状态下使用(Key not valid for use in specified state)。
A:导入带有私钥的证书时,需要使用"X509KeyStorageFlags"参数标记"私钥可导出"。
X509Certificate2 prvcrt = new X509Certificate2(@"X:\path\to\CA.pfx", "***password***", X509KeyStorageFlags.Exportable);
以下为示例程序:
View Code
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace TeatApp_Crypto { using System; using System.Security.Cryptography; using System.Security.Cryptography.X509Certificates; using System.Text; class RSACSPSample { static void Main() { try { //Create a UnicodeEncoder to convert between byte array and string. UnicodeEncoding ByteConverter = new UnicodeEncoding(); //Create byte arrays to hold original, encrypted, and decrypted data. byte[] dataToEncrypt = ByteConverter.GetBytes("Data to Encrypt"); byte[] encryptedData; byte[] decryptedData; X509Certificate2 pubcrt = new X509Certificate2(@"X:\path\to\CA.crt"); RSACryptoServiceProvider pubkey = (RSACryptoServiceProvider)pubcrt.PublicKey.Key; X509Certificate2 prvcrt = new X509Certificate2(@"X:\path\to\CA.pfx", "***password***", X509KeyStorageFlags.Exportable); RSACryptoServiceProvider prvkey = (RSACryptoServiceProvider)prvcrt.PrivateKey; //Create a new instance of RSACryptoServiceProvider to generate //public and private key data. //using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) //{ //Console.WriteLine(RSA.ToXmlString(false)); //Pass the data to ENCRYPT, the public key information //(using RSACryptoServiceProvider.ExportParameters(false), //and a boolean flag specifying no OAEP padding. encryptedData = RSAEncrypt(dataToEncrypt, pubkey.ExportParameters(false), false); Console.WriteLine("Encrypted plaintext: {0}", Convert.ToBase64String(encryptedData)); //Pass the data to DECRYPT, the private key information //(using RSACryptoServiceProvider.ExportParameters(true), //and a boolean flag specifying no OAEP padding. decryptedData = RSADecrypt(encryptedData, prvkey.ExportParameters(true), false); //Display the decrypted plaintext to the console. Console.WriteLine("Decrypted plaintext: {0}", ByteConverter.GetString(decryptedData)); //} prvkey.Clear(); pubkey.Clear(); Console.Read(); } catch (ArgumentNullException) { //Catch this exception in case the encryption did //not succeed. Console.WriteLine("Encryption failed."); } } static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding) { try { byte[] encryptedData; //Create a new instance of RSACryptoServiceProvider. using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) { //Import the RSA Key information. This only needs //toinclude the public key information. RSA.ImportParameters(RSAKeyInfo); //Encrypt the passed byte array and specify OAEP padding. //OAEP padding is only available on Microsoft Windows XP or //later. encryptedData = RSA.Encrypt(DataToEncrypt, DoOAEPPadding); } return encryptedData; } //Catch and display a CryptographicException //to the console. catch (CryptographicException e) { Console.WriteLine(e.Message); return null; } } static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding) { try { byte[] decryptedData; //Create a new instance of RSACryptoServiceProvider. using (RSACryptoServiceProvider RSA = new RSACryptoServiceProvider()) { //Import the RSA Key information. This needs //to include the private key information. RSA.ImportParameters(RSAKeyInfo); //Decrypt the passed byte array and specify OAEP padding. //OAEP padding is only available on Microsoft Windows XP or //later. decryptedData = RSA.Decrypt(DataToDecrypt, DoOAEPPadding); } return decryptedData; } //Catch and display a CryptographicException //to the console. catch (CryptographicException e) { Console.WriteLine(e.ToString()); return null; } } } }