自己写的一个加密,解密(AES)组件

来源:互联网 发布:创世纪 许文彪 知乎 编辑:程序博客网 时间:2024/04/28 02:27

 首先说明:这个组件的加密解密核心还是用的微软提供的AES程序加密、解密。除此之外,我还提供了一个很好的功能。

 

需求说明:

 

1. 用户A上传了一个文档附件,并设置一个密码。这样没有密码的人不能打开这个文件。

2. 用户A同时还选择了几个用户。这样不是选择的用户不能这个文档。

3. 谁能看到这个文档附件?我们限定在只有用户A,和他选定的几个用户。当然,他们还必须知道这个文档的password。

4 有意思的是,这个功能不是靠权限控制的。

 

测试用例:

试用nunit测试工具

  1. #region rar
  2.         [Test]
  3.         public void RarEncodeTest()
  4.         {
  5.             string inFilePath = @"d:/test_file.rar";
  6.             string outFilePath = @"d:/test_file_encoded.rar";
  7.             string key = "asp.net mvc rar";
  8.             IList<string> users = new List<string>();
  9.             users.Add("yaxino");
  10.             users.Add("yinzhiqiang");
  11.             string encodeKey = SecurityFacade.FileEncode(inFilePath, outFilePath, key, users);
  12.             ENCLOSURE enc = new ENCLOSURE();
  13.             enc.ENC_DOC_ID = 1;
  14.             enc.ENC_REMARK = "测试Security rar";
  15.             enc.ENC_URL = outFilePath;
  16.             enc.ENC_PWD = encodeKey;
  17.             int success = new EncLogic().Add(enc, GetDb());
  18.             Assert.AreEqual(1, success, "添加附件信息到数据库失败!");
  19.         }
  20.         [Test]
  21.         public void RarDecodeTest()
  22.         {
  23.             string inFilePath = @"d:/test_file_2.rar";
  24.             string outFilePath = @"d:/test_file_encoded.rar";
  25.             string randomkey = new EncLogic().Get(MaxID(), GetDb()).ENC_PWD; //从数据库取密码密文
  26.             string key = "asp.net mvc rar";
  27.             string user = "yaxino";
  28.             string encodeKey = SecurityFacade.FileDecode(outFilePath, inFilePath, key, user, randomkey);
  29.             Assert.AreEqual(randomkey, encodeKey, "保存密文VS解压密文");
  30.         }
  31.         [Test]
  32.         public void RarDecodeTestWrongUser()
  33.         {
  34.             string inFilePath = @"d:/test_file_2.rar";
  35.             string outFilePath = @"d:/test_file_encoded.rar";
  36.             string randomkey = new EncLogic().Get(MaxID(), GetDb()).ENC_PWD; //从数据库取密码密文
  37.             string key = "asp.net mvc rar";
  38.             string user = "yaxin";
  39.             string encodeKey = SecurityFacade.FileDecode(outFilePath, inFilePath, key, user, randomkey);
  40.             Assert.AreEqual(randomkey, encodeKey, "保存密文VS解压密文");
  41.         }
  42.         [Test]
  43.         public void RarDecodeTestWrongpwd()
  44.         {
  45.             string inFilePath = @"d:/test_file_2.rar";
  46.             string outFilePath = @"d:/test_file_encoded.rar";
  47.             string randomkey = new EncLogic().Get(MaxID(), GetDb()).ENC_PWD; //从数据库取密码密文
  48.             string key = "rar wrong";
  49.             string user = "yaxin";
  50.             string encodeKey = SecurityFacade.FileDecode(outFilePath, inFilePath, key, user, randomkey);
  51.             Assert.AreEqual(randomkey, encodeKey, "保存密文VS解压密文");
  52.         }
  53.         #endregion

 

对外接口,我叫它为安全外观:

  1. public sealed class SecurityFacade
  2.     {
  3.         private static ISecurity security = null;
  4.         /// <summary>
  5.         /// 文件加密外观
  6.         /// </summary>
  7.         /// <param name="inFilePath">输入文件路劲</param>
  8.         /// <param name="outFilePath">输出文件路劲</param>
  9.         /// <param name="key">密钥</param>
  10.         /// <returns>消息</returns>
  11.         public static string FileEncode(string inFilePath, string outFilePath, string key, IList<string> users)
  12.         {
  13.             try
  14.             {
  15.                 security = new FileSecurity();
  16.                 //加密文件,返回随机密钥
  17.                 string randomKey = security.Encode(inFilePath, outFilePath, key);
  18.                 //得到随机密钥key+用户组信息明文
  19.                 string keyUsers = GenerateKeyAndUsers(randomKey, users);
  20.                 security = new TextSecurity();
  21.                 //二次密钥加密,并返回加密密文
  22.                 return security.Encode(keyUsers, "", key);
  23.             }
  24.             catch (Exception ex)
  25.             {
  26.                 return ex.Message;
  27.             }
  28.         }
  29.         /// <summary>
  30.         /// 文件解密外观
  31.         /// 没有异常抛出,返回不正确的文件
  32.         /// </summary>
  33.         /// <param name="outFilePath"></param>
  34.         /// <param name="inFilePath"></param>
  35.         /// <param name="key"></param>
  36.         /// <param name="user"></param>
  37.         /// <param name="randomkeyEncode"></param>
  38.         /// <returns></returns>
  39.         public static string FileDecode(string outFilePath, string inFilePath, string key, string user, string randomkeyEncode)
  40.         {
  41.             try
  42.             {
  43.                 security = new TextSecurity();
  44.                 //解密的编码后的随机密码
  45.                 string randomKeyDecode = security.Decode(randomkeyEncode, "", key);
  46.                 //根据用户,得到随机密钥key
  47.                 string randomKey = GenerateRandomKey(randomKeyDecode, user);
  48.                 security = new FileSecurity();
  49.                 //解密文件
  50.                 return security.Decode(outFilePath, inFilePath, randomKey);
  51.             }
  52.             catch (Exception ex)
  53.             {
  54.                 return ex.Message;
  55.             }
  56.         }
  57.         #region "私有成员"
  58.         private static string GenerateKeyAndUsers(string randomKey, IList<string> users)
  59.         {
  60.             string keyUsers = randomKey;
  61.             foreach (string user in users)
  62.             {
  63.                 keyUsers += "|" + user;
  64.             }
  65.             return keyUsers + "|";
  66.         }
  67.         private static string GenerateRandomKey(string randomKey, string user)
  68.         {
  69.             AesCryptoServiceProvider aes = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
  70.             aes.GenerateIV();
  71.             if (randomKey.IndexOf('|') < 0 || randomKey.IndexOf("|" + user + "|") < 0)
  72.             {
  73.                 return Convert.ToBase64String(aes.IV) + Convert.ToBase64String(aes.Key);
  74.             }
  75.             return randomKey.Substring(0, randomKey.IndexOf('|'));
  76.         }
  77.         
  78.         /// <summary>
  79.         /// 文本加密外观
  80.         /// </summary>
  81.         /// <param name="inString"></param>
  82.         /// <param name="key"></param>
  83.         /// <returns></returns>
  84.         public static string TextEncode(string inString, string key)
  85.         {
  86.             string outString = string.Empty;
  87.             security = new TextSecurity();
  88.             security.Encode(inString, outString, key);
  89.             return outString;
  90.         }
  91.         #endregion
  92.         /// <summary>
  93.         /// 文本解密
  94.         /// 无异常抛出,key不正确,返回密文
  95.         /// </summary>
  96.         /// <param name="inString"></param>
  97.         /// <param name="key"></param>
  98.         /// <returns></returns>
  99.         public static string TextDecode(string inString, string key)
  100.         {
  101.             string outString = string.Empty;
  102.             security = new TextSecurity();
  103.             outString = security.Decode(inString, outString, key);
  104.             return outString;
  105.         }
  106.     }

 

内部实现如下:

 

接口定义:

  1. interface ISecurity
  2.     {
  3.         string Encode(string encodeString, string decodedString, string key);
  4.         string Decode(string decodeString, string decodedString, string key);
  5.     }

 

抽象类:

 

internal abstract class AbstractSecurity : ISecurity
    {
        //文本加密用的向量
        protected static readonly byte[] IV = { 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56};
       
       

        #region ISecurity 成员

        public abstract string Encode(string encodeString, string decodedString, string key);

        public abstract string Decode(string decodeString, string decodedString, string key);

        #endregion
    }

 

 

具体实现类是两个,第一个FileSecurity.cs

 

  1. internal class FileSecurity : AbstractSecurity
  2.     {
  3.         #region ISecurity 成员
  4.         /// <summary>
  5.         /// 文件加密算法:
  6.         /// 对制定路径的文件加密,
  7.         /// 并返回随即生成的IV+密钥base64字符串
  8.         /// 可能抛出异常
  9.         /// </summary>
  10.         /// <param name="inFileName">输入文件完全路劲</param>
  11.         /// <param name="outFileName">输出文件完全路劲</param>
  12.         /// <param name="key"> 随机密钥</param>
  13.         /// <returns></returns>
  14.         public override string Encode(string inFileName, string outFileName, string key)
  15.         {
  16.             
  17.             FileStream fsInput = null;
  18.             FileStream fsEncrypted = null;
  19.             CryptoStream cryptostream = null;
  20.             AesCryptoServiceProvider AES = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
  21.             try
  22.             {
  23.                 fsInput = new FileStream(inFileName, FileMode.Open, FileAccess.Read);
  24.                 fsEncrypted = new FileStream(outFileName, FileMode.Create, FileAccess.Write);
  25.                 AES.GenerateIV();
  26.                 //AES.IV = IV;
  27.                 cryptostream = new CryptoStream(fsEncrypted, AES.CreateEncryptor(), CryptoStreamMode.Write);
  28.                 byte[] bytearrayinput = new byte[fsInput.Length];
  29.                 fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
  30.                 cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
  31.                 cryptostream.FlushFinalBlock();
  32.                 
  33.                 return Convert.ToBase64String(AES.IV) + Convert.ToBase64String(AES.Key);
  34.             }
  35.             catch (Exception ex)
  36.             {
  37.                 throw ex;
  38.                 
  39.             }
  40.             finally
  41.             {
  42.                 fsInput.Close();
  43.                 fsEncrypted.Close();
  44.                 
  45.             }
  46.             
  47.         }
  48.         /// <summary>
  49.         /// 文件解密算法
  50.         /// 不抛出异常
  51.         /// </summary>
  52.         /// <param name="inFileName">输入文件完全路劲</param>
  53.         /// <param name="outFileName">输出文件完全路劲</param>
  54.         /// <param name="key">in 32位密钥</param>
  55.         public override string Decode(string inFileName, string outFileName, string key)
  56.         {
  57.             
  58.             FileStream fsInput = null;
  59.             FileStream fsEncrypted = null;
  60.             CryptoStream cryptostream = null;
  61.             byte[] bytearrayinput = null;
  62.             AesCryptoServiceProvider AES = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
  63.             try
  64.             {
  65.                 fsInput = new FileStream(inFileName, FileMode.Open, FileAccess.Read);
  66.                 fsEncrypted = new FileStream(outFileName, FileMode.Create, FileAccess.Write);
  67.                 //AES.GenerateIV();
  68.                 AES.IV = Convert.FromBase64String( key.Substring(0, key.IndexOf('=') + 2));
  69.                 AES.Key = Convert.FromBase64String(key.Substring(key.IndexOf('=') +2));
  70.                 cryptostream = new CryptoStream(fsEncrypted, AES.CreateDecryptor(), CryptoStreamMode.Write);
  71.                 bytearrayinput = new byte[fsInput.Length];
  72.                 fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
  73.                 cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
  74.                 cryptostream.FlushFinalBlock();
  75.                 
  76.                 return key;
  77.             }
  78.             catch 
  79.             {
  80.                 //throw ex;
  81.                 //出现异常把需要解密的文件直接输出
  82.                 //fsEncrypted.Write(bytearrayinput, 0, bytearrayinput.Length);
  83.                 return key;
  84.             }
  85.             finally
  86.             {
  87.                 fsInput.Close();
  88.                 fsEncrypted.Close();
  89.             }
  90.             
  91.         }
  92.         #endregion
  93.         
  94.     }

 

第二个是TextSecurity.cs

  1. /// <summary>
  2.     /// 文本安全类
  3.     /// </summary>
  4.     internal class TextSecurity : AbstractSecurity
  5.     {
  6.         /// <summary>
  7.         /// 加密文本字符串:
  8.         /// 返回加密后的字符密文
  9.         /// 可能抛出异常
  10.         /// </summary>
  11.         /// <param name="encodeString"></param>
  12.         /// <param name="encodedString"></param>
  13.         /// <param name="key"></param>
  14.         /// <returns></returns>
  15.         public override string Encode(string inString, string nouse, string key)
  16.         {
  17.             try
  18.             {
  19.                 AesCryptoServiceProvider AES = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
  20.                 string encodeKey = Utils.GetSubString(key, 32, "");
  21.                 encodeKey = encodeKey.PadRight(32, '*');
  22.                 AES.Key = Encoding.UTF8.GetBytes(encodeKey.Substring(0, 32));
  23.                 AES.IV = IV;
  24.                 //AES.GenerateIV();
  25.                 byte[] inputByteArray = Encoding.UTF8.GetBytes(inString);
  26.                 MemoryStream mStream = new MemoryStream();
  27.                 CryptoStream cStream = new CryptoStream(mStream, AES.CreateEncryptor(), CryptoStreamMode.Write);
  28.                 cStream.Write(inputByteArray, 0, inputByteArray.Length);
  29.                 cStream.FlushFinalBlock();
  30.                 return Convert.ToBase64String(mStream.ToArray());
  31.             }
  32.             catch (Exception ex)
  33.             {
  34.                 throw ex;
  35.             }
  36.         }
  37.         /// <summary>
  38.         /// 文本解密算法
  39.         /// 不抛出异常
  40.         /// </summary>
  41.         /// <param name="inString"></param>
  42.         /// <param name="nouse"></param>
  43.         /// <param name="key"></param>
  44.         /// <returns></returns>
  45.         public override string Decode(string inString, string nouse, string key)
  46.         {
  47.             byte[] inputByteArray = null;
  48.             try
  49.             {
  50.                 AesCryptoServiceProvider AES = (AesCryptoServiceProvider)AesCryptoServiceProvider.Create();
  51.                 string encodeKey = Utils.GetSubString(key, 32, "");
  52.                 encodeKey = encodeKey.PadRight(32, '*');
  53.                 AES.Key = Encoding.UTF8.GetBytes(encodeKey.Substring(0, 32));
  54.                 AES.IV = IV;
  55.                 //AES.GenerateIV();
  56.                 inputByteArray = Convert.FromBase64String(inString);
  57.                 MemoryStream mStream = new MemoryStream();
  58.                 CryptoStream cStream = new CryptoStream(mStream, AES.CreateDecryptor(), CryptoStreamMode.Write);
  59.                 cStream.Write(inputByteArray, 0, inputByteArray.Length);
  60.                 cStream.FlushFinalBlock();
  61.                 return Encoding.UTF8.GetString(mStream.ToArray());
  62.             }
  63.             catch (Exception ex)
  64.             {
  65.                 //throw ex;
  66.                 //出现异常,直接返回inString
  67.                 return inString;
  68.             }
  69.         }
  70.     }

 

 

打完收工。其中有一个数据库操作,自己弄一下吧。没什么难度。

 

有什么好的建议,请大家指教!

 

我的qq:124391404

email:yzq124391@126.com

原创粉丝点击