c#加密解密文件
利用 .NET 的原生的类库对文件、字符串进行加解密可以说是很简单的一件事情(在这里只讨论对称加解密)。在加解密的时候,最核心事情实际上就是创建一个 CryptoStream 对象,将数据流链接到加密/解密转换的流,然后再将数据写入流中去,这样就完成了一次加密/解密操作。
可能用简单的代码片段更加明白一些,当然,如果这些类一点都不熟的话,还是需要看MSDN的。
public static byte[] Encrypt(String plainText, ICryptoTransform encryptTransform) { try { // Create a memory stream. MemoryStream ms = new MemoryStream(); // Create a CryptoStream using the memory stream. CryptoStream encStream = new CryptoStream(ms, encryptTransform, CryptoStreamMode.Write); // Create a StreamWriter to write a string to the stream. StreamWriter sw = new StreamWriter(encStream); // Write the plain text to the stream. sw.WriteLine(plainText); // Close the StreamWriter and CryptoStream. sw.Close(); encStream.Close(); // Get an array of bytes that represents the memory stream. byte[] buffer = ms.ToArray(); // Close the memory stream. ms.Close(); // Return the encrypted byte array. return buffer; } catch (System.Exception ex) { } return null; }如上代码:
其中参数 encryptTransform 就是要进行加密转换的流,该流是继承于 ICryptoTransform 对象,当然,如果是要解密,那就需要传入解密的转换流。
加密过程已通过注释解释清楚了,相信你能看明白。
但是,有个问题,这些加密、解密的流如何产生出来?
实际上,在进行加密、解密的时候,他们是通过加密算法对象生成出来的。在对称加密算法的基类: SymmetricAlgorithm 类中,我们看到,有两个接口:
当在派生类中重写时,用指定的 Key 属性和初始化向量 (IV) 创建对称解密器对象。 public abstract ICryptoTransform CreateDecryptor( byte[] rgbKey, byte[] rgbIV ) public abstract ICryptoTransform CreateEncryptor( byte[] rgbKey, byte[] rgbIV )
从这两个接口来看,只要是继承于对称加密基类的(如DESCryptoServiceProvider, RijndaelManaged,TripleDESCryptoServiceProvider),都是需要实现这两个接口的。
OK,废话说了一堆,直接写代码吧。
这里分为两个类,其中一个类用于创建加密Key(或者称为加密Provider)----GTXKeyManager,它专注于创建各种类型的加密key和其相关操作,另一个专注于加密和解密----GTXSymmetricCrypt。
/*! * @file GTXKeyManager.cs * * @brief This file implements the class of GTXKeyManager. * This class is used to create encrypt or decrypt provider. * * Copyright (C) 2011, GTX. * * @author Liu Lin * @date 2011/7/01 */ using System; using System.Security.AccessControl; using System.Security.Cryptography; using System.Security.Principal; using GTXUtility.DataStorage.Serializer; namespace GTXUtility.Security.Crypt { public class GTXKeyManager { /// <summary> /// Defines Symmetric Encryption Algorithm types. /// </summary> /// <remarks>The RC2 algorithm cannot be used for GTXXmlCrypt class to encrypt/decrypt XML.</remarks> public enum SymmetricAlgTypes { Unknown, DES = 1, AES128, // Rijndael 128 AES192, // Rijndael 192 AES256, // Rijndael 256 TripleDES, RC2, } /// <summary> /// Create a Symmetric Encryption Algorithm object. /// </summary> /// <param name="salType">Specified symmetric encryption algorithm type.</param> /// <returns>If create success, returns the Symmetric Encryption Algorithm object. /// Otherwise, return null object.</returns> public static SymmetricAlgorithm CreateSymmetricAlgorithm(SymmetricAlgTypes salType) { SymmetricAlgorithm symAlg = null; switch (salType) { case SymmetricAlgTypes.DES: symAlg = SymmetricAlgorithm.Create("DES"); break; case SymmetricAlgTypes.AES128: symAlg = SymmetricAlgorithm.Create("Rijndael"); symAlg.KeySize = 128; break; case SymmetricAlgTypes.AES192: symAlg = SymmetricAlgorithm.Create("Rijndael"); symAlg.KeySize = 192; break; case SymmetricAlgTypes.AES256: symAlg = SymmetricAlgorithm.Create("Rijndael"); symAlg.KeySize = 256; break; case SymmetricAlgTypes.TripleDES: symAlg = SymmetricAlgorithm.Create("TripleDES"); break; case SymmetricAlgTypes.RC2: symAlg = SymmetricAlgorithm.Create("RC2"); break; default: break; } return symAlg; } /// <summary> /// Get the symmetric encryption algorithm type. /// </summary> /// <param name="key">Specified encryption key.</param> /// <returns>Return the symmetric encryption algorithm type.</returns> public static SymmetricAlgTypes GetSymmetricAlgorithmType(SymmetricAlgorithm key) { SymmetricAlgTypes type = SymmetricAlgTypes.Unknown; if (key is DES) { type = SymmetricAlgTypes.DES; } else if (key is Rijndael) { switch ((key as Rijndael).KeySize) { case 128: type = SymmetricAlgTypes.AES128; break; case 192: type = SymmetricAlgTypes.AES192; break; case 256: type = SymmetricAlgTypes.AES256; break; default: break; } } else if (key is TripleDES) { type = SymmetricAlgTypes.TripleDES; } return type; } /// <summary> /// Generate symmetric encryption algorithm key's data. /// </summary> /// <param name="salType">Specified symmetric encryption algorithm type.</param> /// <returns>Return symmetric encryption algorithm key's data.</returns> public static byte[] GenerateKey(SymmetricAlgTypes salType) { SymmetricAlgorithm symAlg = CreateSymmetricAlgorithm(salType); return symAlg.Key; } /// <summary> /// Generate symmetric encryption algorithm key's IV data. /// </summary> /// <param name="salType">Specified symmetric encryption algorithm type.</param> /// <returns>Return symmetric encryption algorithm key's IV data.</returns> public static byte[] GenerateIV(SymmetricAlgTypes salType) { SymmetricAlgorithm symAlg = CreateSymmetricAlgorithm(salType); return symAlg.IV; } } }当然,在GTXKeyManager类中还有其它事情需要做,如加密key的导入导出等工作。这里我就不再粘贴代码了。
/*! * @file GTXXmlCrypt.cs * * @brief This file implements the class of GTXSymmetricCrypt. * This class is used to crypt or decrypt string or file with symmetric algorithm. * * Copyright (C) 2011, GTX. * * @author Liu Lin * @date 2011/7/01 */ using System; using System.IO; using System.Security.Cryptography; using System.Text; namespace GTXUtility.Security.Crypt { /// <summary> /// This class is used to crypt or decrypt string or file with symmetric algorithm. /// </summary> public class GTXSymmetricCrypt { /// <summary> /// Create a encryption/decryption transform. The transform object is used to encrypt or decrypt. /// </summary> /// <param name="symAlgKey">Specified symmetric encryption algorithm provider (key).</param> /// <param name="bCreateEncryptor">If true, create encryption transform, otherwise, create decryption transform</param> /// <returns>Return the encryption/decryption transform.</returns> public static ICryptoTransform CreateCryptoTransform(SymmetricAlgorithm symAlgKey, bool bCreateEncryptor) { try { // If bCreateEncryptor is true, create a encryption ICryptoTransform; // else, create a decryption ICryptoTransform; return bCreateEncryptor ? symAlgKey.CreateEncryptor(symAlgKey.Key, symAlgKey.IV) : symAlgKey.CreateDecryptor(symAlgKey.Key, symAlgKey.IV); } catch (System.Exception ex) { } return null; } /// <summary> /// Create a encryption/decryption transform. The transform object is used to encrypt or decrypt. /// </summary> /// <param name="symAlgType">Specified symmetric algorithm type.</param> /// <param name="rgbKey">Specified key's data of symmetric encryption/decryption algorithm.</param> /// <param name="rgbIV">Specified key's IV of symmetric encryption/decryption algorithm.</param> /// <param name="bCreateEncryptor">If true, create encryption transform, otherwise, create decryption transform</param> /// <returns>Return the encryption/decryption transform.</returns> public static ICryptoTransform CreateCryptoTransform( GTXKeyManager.SymmetricAlgTypes symAlgType, byte[] rgbKey, byte[] rgbIV, bool bCreateEncryptor) { try { // Create a crypt provider by specified type. SymmetricAlgorithm symAlg = GTXKeyManager.CreateSymmetricAlgorithm(symAlgType); // If bCreateEncryptor is true, create a encryption ICryptoTransform; // else, create a decryption ICryptoTransform; return bCreateEncryptor ? symAlg.CreateEncryptor(rgbKey, rgbIV) : symAlg.CreateDecryptor(rgbKey, rgbIV); } catch (System.Exception ex) { } return null; } /// <summary> /// Encrypt a string with encryption transform. /// </summary> /// <param name="plainText">Specified sting which needs to be encrypted.</param> /// <param name="encryptTransform">Specified transform object which used to encrypt.</param> /// <returns>Return the encrypted data. If failed, return null.</returns> public static byte[] Encrypt(String plainText, ICryptoTransform encryptTransform) { try { // Create a memory stream. MemoryStream ms = new MemoryStream(); // Create a CryptoStream using the memory stream. CryptoStream encStream = new CryptoStream(ms, encryptTransform, CryptoStreamMode.Write); // Create a StreamWriter to write a string to the stream. StreamWriter sw = new StreamWriter(encStream); // Write the plain text to the stream. sw.WriteLine(plainText); // Close the StreamWriter and CryptoStream. sw.Close(); encStream.Close(); // Get an array of bytes that represents the memory stream. byte[] buffer = ms.ToArray(); // Close the memory stream. ms.Close(); // Return the encrypted byte array. return buffer; } catch (System.Exception ex) { } return null; } /// <summary> /// Encrypt the specified source file to the specified destination file. /// </summary> /// <param name="sourceFilePath">Specified source file which needs to be encrypted.</param> /// <param name="destFilePath">Specified destination file.</param> /// <param name="encryptTransform">Specified transform object which used to encrypt.</param> /// <returns>If encrypt file succeed, return true, otherwise, return false.</returns> public static bool EncryptFile(String sourceFilePath, String destFilePath, ICryptoTransform encryptTransform) { if (!File.Exists(sourceFilePath)) { return false; } try { FileStream fsSource = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read); FileStream fsDestination = new FileStream(destFilePath, FileMode.OpenOrCreate, FileAccess.Write); // Create a CryptoStream using the memory stream. CryptoStream encStream = new CryptoStream(fsDestination, encryptTransform, CryptoStreamMode.Write); // Create a StreamWriter to write a string to the stream. StreamWriter sw = new StreamWriter(encStream, Encoding.UTF8); // Create a StreamReader to read the file stream to stream. StreamReader sr = new StreamReader(fsSource, Encoding.UTF8); // Print the contents of the destination file. sw.WriteLine(sr.ReadToEnd()); sw.Flush(); // Close the streams. sr.Close(); sw.Close(); encStream.Close(); fsSource.Close(); fsDestination.Close(); return true; } catch (System.Exception ex) { } return false; } /// <summary> /// Decrypt the encrypted byte array into string with decryption transform. /// </summary> /// <param name="cypherText">Specified encrypted byte array.</param> /// <param name="decryptTransform">Specified transform object which used to decrypt.</param> /// <returns>Returns the decrypt string.</returns> public static String Decrypt(byte[] cypherText, ICryptoTransform decryptTransform) { try { // Create a memory stream to the passed buffer. MemoryStream ms = new MemoryStream(cypherText); // Create a CryptoStream using the memory stream and the CSP DES key. CryptoStream decStream = new CryptoStream(ms, decryptTransform, CryptoStreamMode.Read); // Create a StreamReader for reading the stream. StreamReader sr = new StreamReader(decStream); // Read the stream as a string. string val = sr.ReadLine(); // Close the streams. sr.Close(); decStream.Close(); ms.Close(); return val; } catch (System.Exception ex) { } return String.Empty; } /// <summary> /// Decrypt the specified source file to the specified destination file. /// </summary> /// <param name="sourceFilePath">Specified source file which needs to be decrypted.</param> /// <param name="destFilePath">Specified destination file.</param> /// <param name="encryptTransform">Specified transform object which used to decrypt.</param> /// <returns>If decrypt file succeed, return true, otherwise, return false.</returns> public static bool DecryptFile(String sourceFilePath, String destFilePath, ICryptoTransform decryptTransform) { if (!File.Exists(sourceFilePath)) { return false; } try { FileStream fsSource = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read); FileStream fsDestination = new FileStream(destFilePath, FileMode.OpenOrCreate, FileAccess.Write); // Create a CryptoStream using the memory stream and the CSP DES key. CryptoStream decStream = new CryptoStream(fsSource, decryptTransform, CryptoStreamMode.Read); // Create a StreamWriter to write a string to the stream. StreamWriter sw = new StreamWriter(fsDestination, Encoding.UTF8); // Create a StreamReader to read the decrypted stream. StreamReader sr = new StreamReader(decStream, Encoding.UTF8); // Print the contents of the destination file. sw.WriteLine(sr.ReadToEnd()); sw.Flush(); // Close the streams. sr.Close(); sw.Close(); decStream.Close(); fsSource.Close(); fsDestination.Close(); return true; } catch (System.Exception ex) { } return false; } } }测试代码:
using System; using System.IO; using System.Security.Cryptography; using System.Text; using GTXUtility.Security.Crypt; namespace TestUtility { public class TestSymmetricCrypt { // The secret key to use for the DES symmetric algorithm. public static readonly byte[] Default_DES_Key = { 34, 63, 63, 109, 63, 119, 63, 63 }; // The initialization vector to use for the DES symmetric algorithm. public static readonly byte[] Default_DES_IV = { 34, 63, 63, 109, 63, 119, 63, 63 }; private readonly static String _plainText1 = "这是明文。This is a test plain Text!"; public static void UseDemo() { Console.WriteLine("Select test type (Default is O): 0: string encryption/decryption, otherwise, test file encryption/decryption"); String type = Console.ReadLine(); int nType = type.Equals("0") ? 0 : 1; if (0 == nType) { TestCryptString(); } else { TestCryptFile(); } } public static void TestCryptString() { Console.WriteLine("\n№ Encrypt/Decrypt Plain Text by specified symmetric algorithm."); Console.WriteLine("→ Original Plain Text: {0}", _plainText1); // Create a symmetric algorithm encryption provider. GTXKeyManager.SymmetricAlgTypes salType = ReadSymmetricAlgType(); SymmetricAlgorithm symAlg = GTXKeyManager.CreateSymmetricAlgorithm(salType); // Create a ICryptoTransform object to encrypt. ICryptoTransform encryptTransform = GTXSymmetricCrypt.CreateCryptoTransform(symAlg, true); byte[] cypherText = GTXSymmetricCrypt.Encrypt(_plainText1, encryptTransform); Console.WriteLine("→ Cypher Text: {0}", Encoding.ASCII.GetString(cypherText)); // Create a ICryptoTransform object to decrypt. ICryptoTransform decryptTransform = GTXSymmetricCrypt.CreateCryptoTransform(symAlg, false); String tempPlainText = GTXSymmetricCrypt.Decrypt(cypherText, decryptTransform); Console.WriteLine("→ Decrypt Cypher Text: {0}", tempPlainText.ToString()); //------------------------------------------------------------------------------ // Use DES Key and IV to encrypt and decrypt string. // Create a ICryptoTransform object to encrypt. Console.WriteLine("\n№ Encrypt/Decrypt Plain Text by specified Key and IV. (DES)"); encryptTransform = GTXSymmetricCrypt.CreateCryptoTransform(GTXKeyManager.SymmetricAlgTypes.DES, Default_DES_Key, Default_DES_IV, true); cypherText = GTXSymmetricCrypt.Encrypt(_plainText1, encryptTransform); Console.WriteLine("→ Cypher Text: {0}", Encoding.ASCII.GetString(cypherText)); // Create a ICryptoTransform object to decrypt. decryptTransform = GTXSymmetricCrypt.CreateCryptoTransform(GTXKeyManager.SymmetricAlgTypes.DES, Default_DES_Key, Default_DES_IV, false); tempPlainText = GTXSymmetricCrypt.Decrypt(cypherText, decryptTransform); Console.WriteLine("→ Decrypt Cypher Text: {0}", tempPlainText.ToString()); } public static void TestCryptFile() { Console.WriteLine("Test file Crypt begin..."); Console.WriteLine("Input file path: (You can drag a file into console without input file path)"); String filePath = Console.ReadLine(); if (File.Exists(filePath)) { using (FileStream fs = new FileStream(filePath, FileMode.Open)) { StreamReader sr = new StreamReader(fs, Encoding.UTF8); Console.WriteLine("■ Original file:\n{0}", sr.ReadToEnd()); sr.Close(); } GTXKeyManager.SymmetricAlgTypes salType = ReadSymmetricAlgType(); // Create a symmetric algorithm encryption provider. SymmetricAlgorithm symAlg = GTXKeyManager.CreateSymmetricAlgorithm(salType); // Create a ICryptoTransform object to encrypt. ICryptoTransform encryptTransform = GTXSymmetricCrypt.CreateCryptoTransform(symAlg, true); if (GTXSymmetricCrypt.EncryptFile(filePath, "Encrypted.txt", encryptTransform)) { using (FileStream fs = new FileStream("Encrypted.txt", FileMode.Open)) { StreamReader sr = new StreamReader(fs, Encoding.UTF8); Console.WriteLine("■ Encrypted file:\n{0}", sr.ReadToEnd()); sr.Close(); } } // Create a ICryptoTransform object to decrypt. ICryptoTransform decryptTransform = GTXSymmetricCrypt.CreateCryptoTransform(symAlg, false); if (GTXSymmetricCrypt.DecryptFile("Encrypted.txt", "Decrypted.txt", decryptTransform)) { using (FileStream fs = new FileStream("Decrypted.txt", FileMode.Open)) { StreamReader sr = new StreamReader(fs, Encoding.UTF8); Console.WriteLine("■ Decrypted file:\n{0}", sr.ReadToEnd()); sr.Close(); } } } } private static GTXKeyManager.SymmetricAlgTypes ReadSymmetricAlgType() { Console.WriteLine("Select the encrypt/decrypt algorithm: (Default is DES)"); for (GTXKeyManager.SymmetricAlgTypes salTypeTemp = GTXKeyManager.SymmetricAlgTypes.DES; salTypeTemp <= GTXKeyManager.SymmetricAlgTypes.RC2; ++salTypeTemp) { Console.WriteLine("{0} is {1}", (int)salTypeTemp, salTypeTemp.ToString()); } // Read the symmetric algorithm command String algString = Console.ReadLine(); GTXKeyManager.SymmetricAlgTypes salType = GTXKeyManager.SymmetricAlgTypes.DES; try { salType = (GTXKeyManager.SymmetricAlgTypes)Convert.ToInt32(algString); if (salType <= GTXKeyManager.SymmetricAlgTypes.DES && salType >= GTXKeyManager.SymmetricAlgTypes.TripleDES) { salType = GTXKeyManager.SymmetricAlgTypes.DES; } } catch (System.Exception ex) { salType = GTXKeyManager.SymmetricAlgTypes.DES; } return salType; } } }