这几天在写一个对文件进行加密解密的程序,翻了以前在博客园贴过的一段代码,稍微整理了一下,写成一个方便调用的类,并做了注释。
这里需要特别说明的是,AES 需要提供2个字符串,一个是KEY,一个是IV,并且都有长度要求。但对于一般的加密来说,是比较麻烦的。所以我还提供了一个方便调用的 Simple 方法,只需提供一个密码,通过 MD5 自动处理为 32 位长度的 KEY,并截取其中 16 位作为 IV,这样在调用的时候,也方便许多。
经过试用,觉得 AES 256 在加密小文件的时候,效率是可以的,但加密大文件(例如 1.25G 的视频)效率明显下降,并且占用系统资源很大。
以下是代码:
using System.Security.Cryptography;
using System.Text;
// 阿博-STYLE
// www.abo-style.com
namespace AboStyle
{
/// <summary>
/// AES 256 加密和解密 for C#
/// 阿博-STYLE(2012)
/// </summary>
public class Aes
{
#region Create
/// <summary>
/// 创建一个统一配置的加密算法。
/// </summary>
/// <param name="key">密钥(32位)</param>
/// <param name="iv">初始化向量(16位)</param>
/// <returns>RijndaelManaged</returns>
private static RijndaelManaged Create(string key, string iv)
{
RijndaelManaged rm = new RijndaelManaged();
rm.Key = Encoding.UTF8.GetBytes(key); // 这里统一使用UTF8进行编码;
rm.IV = Encoding.UTF8.GetBytes(iv); // 如果使用其它编码,要注意长度问题;
rm.Mode = CipherMode.CBC;
rm.Padding = PaddingMode.PKCS7;
return rm;
}
#endregion
#region Encryptor
/// <summary>
/// 对字节数组进行加密
/// </summary>
/// <param name="bs">要加密的字节</param>
/// <param name="key">密钥(32位)</param>
/// <param name="iv">初始化向量(16位)</param>
/// <returns>加密后的结果</returns>
public static byte[] Encryptor(byte[] bs, string key, string iv)
{
ICryptoTransform transform = Create(key, iv).CreateEncryptor();
return transform.TransformFinalBlock(bs, 0, bs.Length);
}
#endregion
#region Decryptor
/// <summary>
/// 对字节数组进行解密
/// </summary>
/// <param name="bs">要解密的字节</param>
/// <param name="key">密钥(32位)</param>
/// <param name="iv">初始化向量(16位)</param>
/// <returns>解密后的结果</returns>
public static byte[] Decryptor(byte[] bs, string key, string iv)
{
ICryptoTransform transform = Create(key, iv).CreateDecryptor();
return transform.TransformFinalBlock(bs, 0, bs.Length);
}
#endregion
#region Simple
/// <summary>
/// 方便简单调用的加密或解密统一方法
/// </summary>
/// <param name="encrypt">是否为加密?true 为加密,false 为解密</param>
/// <param name="bs">要加密或解密的字节</param>
/// <param name="password">密码(任意长度,使用MD5处理为32位)</param>
/// <returns>处理后的字节</returns>
public static byte[] Simple(bool encrypt, byte[] bs, string password)
{
// 借用 MD5 算法,将密码统一为32位长度字符串
StringBuilder md5 = new StringBuilder();
foreach (byte b in System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(password)))
{
md5.Append(b.ToString("X2"));
}
// KEY 为 MD5
string key = md5.ToString();
// IV 为 MD5 中截取中间的16位字符
string iv = key.Substring(8, 16);
// 根据是否加密 调用不同的方法
return encrypt ? Encryptor(bs, key, iv) : Decryptor(bs, key, iv);
}
#endregion
}
}