前言:
本文只介绍How to use,对于加密算法的研究不予讨论。
关于私钥的存储,微软给的建议是使用windows自带的秘钥容器,相见文档。
为了直观看到私钥和公钥,本文直接将其存入XML文件中。现实情况则要复杂的多,还牵涉到数字签名、数字证书等。
关于公钥、私钥、数字签名、数字证书的概念,相见阮一峰大神的博客,传送门在这里。
正文:
由于RSA不适合加密大量数据,所以可以采用DES和RSA混合加密的方法,即先用DES加密数据,再用RSA加密DES的秘钥。
RSAHelper 类
public class RSAHelper { /// <summary> /// 读取二进制文件 /// </summary> /// <param name="path"></param> /// <returns></returns> public static byte[] GetByte(string path) { FileInfo fi = new FileInfo(path); List<byte> buff = new List<byte>(); using (FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) { BinaryReader br = new BinaryReader(fs); try { while (true) { byte i = br.ReadByte(); buff.Add(i); } } catch (Exception) { br.Close(); } } return buff.ToArray(); } /// <summary> /// 读取文本文件 /// </summary> /// <param name="path"></param> /// <returns></returns> public static string GetText(string path) { FileInfo fi = new FileInfo(path); string content; using (FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) { StreamReader sr = new StreamReader(fs); content = sr.ReadToEnd(); sr.Close(); } return content; } /// <summary> /// 写入二进制文件 /// </summary> /// <param name="content"></param> /// <param name="path"></param> public static void WriteByte(byte[] content, string path) { FileInfo fi = new FileInfo(path); using (FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) { BinaryWriter br = new BinaryWriter(fs); br.Write(content); br.Flush(); br.Close(); } } /// <summary> /// 写入文本文件 /// </summary> /// <param name="content"></param> /// <param name="path"></param> public static void WriteText(string content, string path) { FileInfo fi = new FileInfo(path); using (FileStream fs = fi.Open(FileMode.OpenOrCreate, FileAccess.ReadWrite)) { StreamWriter sw = new StreamWriter(fs); sw.Write(content); sw.Flush(); sw.Close(); } } /// <summary> /// RSA加密/解密 /// </summary> /// <param name="data">加密/解密数据</param> /// <param name="key">公钥/私钥</param> /// <param name="isEncrypt">ture加密,false解密</param> /// <returns></returns> public static byte[] EncryptOrDecrypt(byte[] data, string key, bool isEncrypt) { RSACryptoServiceProvider rsaP = new RSACryptoServiceProvider(); rsaP.FromXmlString(key); if (isEncrypt)// 加密 { byte[] buff = rsaP.Encrypt(data, true); return buff; } else // 解密 { byte[] buff = rsaP.Decrypt(data, true); return buff; } } }
DESHelper 类
public class DESHelper { /// <summary> /// DES加密/解密 /// </summary> /// <param name="data">加密/解密数据</param> /// <param name="key">秘钥</param> /// <param name="keyIV">向量</param> /// <param name="isEncrypt">true加密,false解密</param> /// <returns></returns> public static byte[] EncryptOrDecrypt(byte[] data, byte[] key, byte[] keyIV, bool isEncrypt) { DESCryptoServiceProvider desP = new DESCryptoServiceProvider(); if (isEncrypt)// 加密 { desP.Key = key; desP.IV = keyIV; ICryptoTransform desencrypt = desP.CreateEncryptor(key, keyIV); byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length); return result; } else // 解密 { desP.Key = key; desP.IV = keyIV; ICryptoTransform desencrypt = desP.CreateDecryptor(key, keyIV); byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length); return result; } } /// <summary> /// 创建随机秘钥 /// </summary> /// <returns></returns> public static byte[] CreateKey() { DESCryptoServiceProvider desP = new DESCryptoServiceProvider(); desP.GenerateKey(); return desP.Key; } /// <summary> /// 创建随机向量 /// </summary> /// <returns></returns> public static byte[] CreateIV() { DESCryptoServiceProvider desP = new DESCryptoServiceProvider(); desP.GenerateIV(); return desP.IV; } }
主程序代码
class Program { static void Main(string[] args) { string rootPath = AppDomain.CurrentDomain.BaseDirectory; string RSAPath = Path.Combine(rootPath, "RSA"); string encryptFilePath = Path.Combine(RSAPath, "加密文件.dll"); string decryptFilePath = Path.Combine(RSAPath, "解密文件.txt"); string publicKeyPath = Path.Combine(RSAPath, "RSA公钥.xml"); string privateKeyPath = Path.Combine(RSAPath, "RSA私钥.xml"); string DESKeyPath = Path.Combine(RSAPath, "经过RSA加密的DES秘钥.dll"); string DESIVPath = Path.Combine(RSAPath, "经过RSA加密的DES向量.dll"); if (Directory.Exists(RSAPath)) { Directory.Delete(RSAPath, true); } Directory.CreateDirectory(RSAPath); Console.WriteLine("请输入要加密的内容:"); string data = Console.ReadLine(); RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(); string RSAPublic = rsa.ToXmlString(false);// RSA公钥 string RSAPrivate = rsa.ToXmlString(true);// RSA私钥 byte[] DESKey = DESHelper.CreateKey(); // DES秘钥 byte[] DESIV = DESHelper.CreateIV(); // DES向量 // DES加密输入内容 byte[] enData = DESHelper.EncryptOrDecrypt(Encoding.Unicode.GetBytes(data), DESKey, DESIV, true); // 写入加密文件 RSAHelper.WriteByte(enData, encryptFilePath); // 写入RSA公钥 RSAHelper.WriteText(RSAPublic, publicKeyPath); // 写入RSA私钥 RSAHelper.WriteText(RSAPrivate, privateKeyPath); // 写入经过RSA加密的DES秘钥 RSAHelper.WriteByte(RSAHelper.EncryptOrDecrypt(DESKey, RSAPublic, true), DESKeyPath); // 写入经过RSA加密的DES向量 RSAHelper.WriteByte(RSAHelper.EncryptOrDecrypt(DESIV, RSAPublic, true), DESIVPath); // 读取RSA私钥 string privateKey = RSAHelper.GetText(privateKeyPath); // 读取DES秘钥并解密 byte[] realDESKey = RSAHelper.EncryptOrDecrypt(RSAHelper.GetByte(DESKeyPath), privateKey, false); // 读取DES向量并解密 byte[] realDESIV = RSAHelper.EncryptOrDecrypt(RSAHelper.GetByte(DESIVPath), privateKey, false); // 读取加密文件 byte[] enData2 = RSAHelper.GetByte(encryptFilePath); // 解密文件 byte[] deData = DESHelper.EncryptOrDecrypt(enData2, realDESKey, realDESIV, false); // 写入解密文件 RSAHelper.WriteText(Encoding.Unicode.GetString(deData), decryptFilePath); Console.WriteLine("加密成功!"); Console.ReadKey(); } }
运行效果:
(完)