• 技巧篇:结合反射技术实现多算法动态加密


    这个题目,我姑且这样叫吧,照例,我们先来分析一下需求。
    比如有一个设置密码的功能,但用户希望能够自己选择密码的加密算法,如MD5、HMAC、SHA1等,然后程序会根据用户所选择的算法对密码进行加密并存入数据库,同时在配置文件中记录下用户的选择。
    按照一般的思路,我们可能会做一个分支判断,如
    1. switch( 用户的选择 )  
    2. {  
    3.     case "MD5":  
    4.               MD5 md5 = MD5.Create();..............         
    5.               break;  
    6.              ...........  
    7. }  


     

    呵呵,其实我们不必要这样做,来,先来看看MD5、HMAC、SHA1、SHA384等类有什么共同的特征?
    1、都是通过调用Create静态方法来创建一个实例,当然,像MD5这些类都是抽象类,是不能被实例化的。其实,它们都返回一个名为“算法名CryptoServiceProvider”的类实例,如MD5CryptoServiceProvider、SHA1CryptoServiceProvider等,这些类都是对算法计算的具体实现。
    2、都是通过调用ComputeHash方法计算哈希值的。
     
    而且,这些类都是位于同一个命名空间下,因些,根据不同的算法进行加密,唯一不同的是类名,也就是说,我们的代码只写一次就可以了,把代码封装在一个方法中,通过在参数中传递类名。
     
    能做到这种功夫的,也就用到反射了,通过反射动态动调用类成员来完成。
    1. /// <summary>  
    2. /// 通过算法计算哈希值。  
    3. /// </summary>  
    4. /// <param name="className">算法类名</param>  
    5. /// <param name="tcode">待加密的字符串</param>  
    6. /// <returns>加密后的字节数组</returns>  
    7. private byte[] ComputeHash(string className, string tcode)  
    8. {  
    9.     byte[] bufRes = null;  
    10.     // 加载程序集  
    11.     Assembly asmby = Assembly.Load(@"mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");  
    12.     Type myType = asmby.GetType("System.Security.Cryptography." + className, false, true);  
    13.     if (myType != null)  
    14.     {  
    15.         // 得到与Create方法有关的MethodInfo  
    16.         // GetMethod通过传入的Type数组的维数和类型来  
    17.         // 判断获取哪个重载。  
    18.         MethodInfo mdf=myType.GetMethod("Create",new Type[0]);  
    19.         if (mdf != null)  
    20.         {  
    21.             object ob = null;  
    22.             // 调用方法  
    23.             ob = mdf.Invoke(null, null);  
    24.             if (ob != null)  
    25.             {  
    26.                 // 得到ComputeHash方法的MethodInfo  
    27.                 MethodInfo mfo = myType.GetMethod("ComputeHash", new Type[] { typeof(byte[]) });  
    28.                 if (mfo!=null)  
    29.                 {  
    30.                     // 调用方法  
    31.                     bufRes = (byte[])mfo.Invoke(ob, new object[]{  
    32.                         Encoding.Default.GetBytes(tcode)  
    33.                     });  
    34.                 }  
    35.             }  
    36.         }  
    37.     }  
    38.     return bufRes;  
    39. }  


     

    接着需要一个方法来把字节数组转为字符串。
    1. /// <summary>  
    2. /// 把字节数组转换为十六进制字符串。  
    3. /// </summary>  
    4. /// <param name="bf"></param>  
    5. /// <returns></returns>  
    6. private string ByteToStr(byte[] bf)  
    7. {  
    8.     StringBuilder sb = new StringBuilder();  
    9.     foreach (byte b in bf)  
    10.     {  
    11.         sb.Append(b.ToString("x2"));  
    12.     }  
    13.     return sb.ToString();  
    14. }  


     

    然后,我们就可以在其它代码中使用了。
    1. public partial class b : Form  
    2. {  
    3.     public b()  
    4.     {  
    5.         InitializeComponent();  
    6.         comboBox1.Items.Add("HMAC");  
    7.         comboBox1.Items.Add("MD5");  
    8.         comboBox1.Items.Add("SHA1");  
    9.         comboBox1.Items.Add("SHA256");  
    10.         comboBox1.Items.Add("SHA384");  
    11.         comboBox1.Items.Add("SHA512");  
    12.         comboBox1.Items.Add("RIPEMD160");  
    13.         comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;  
    14.         comboBox1.SelectedIndex = 0;  
    15.     }  
    16.   
    17.     private void button1_Click(object sender, EventArgs e)  
    18.     {  
    19.         if (comboBox1.SelectedIndex == -1)  
    20.         {  
    21.             return;  
    22.         }  
    23.         try  
    24.         {  
    25.             byte[] bHash = ComputeHash(comboBox1.SelectedItem.ToString(), txtIn.Text);  
    26.             if (bHash != null)  
    27.             {  
    28.                 txtOut.Text = ByteToStr(bHash);  
    29.             }  
    30.         }  
    31.         catch (Exception ex)  
    32.         {  
    33.             MessageBox.Show(ex.Message);  
    34.         }  
    35.     }  


     

    好了,现在可以运行一个试试。

  • 相关阅读:
    macbook如何清理磁盘中的“容器中的其他宗卷”
    Maven本地仓库与远程仓库配置
    查看MySQL库、表所占磁盘空间大小
    数据库操作
    Mac Mysql初始密码重置
    Vue 性能优化经验总结
    【读书笔记】对象创建摘录
    【读书笔记】 函数柯里化
    js实现仿windows文件按名称排序
    本来想偷懒的今天,想了想,还是写一篇吧,前端登录界面,用的BOOTSTRAP
  • 原文地址:https://www.cnblogs.com/xieweikai/p/6832827.html
Copyright © 2020-2023  润新知