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

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


呵呵,其实我们不必要这样做,来,先来看看MD5、HMAC、SHA1、SHA384等类有什么共同的特征?
1、都是通过调用Create静态方法来创建一个实例,当然,像MD5这些类都是抽象类,是不能被实例化的。其实,它们都返回一个名为“算法名CryptoServiceProvider”的类实例,如MD5CryptoServiceProvider、SHA1CryptoServiceProvider等,这些类都是对算法计算的具体实现。
2、都是通过调用ComputeHash方法计算哈希值的。
而且,这些类都是位于同一个命名空间下,因些,根据不同的算法进行加密,唯一不同的是类名,也就是说,我们的代码只写一次就可以了,把代码封装在一个方法中,通过在参数中传递类名。
能做到这种功夫的,也就用到反射了,通过反射动态动调用类成员来完成。

        /// <summary>
        /// 通过算法计算哈希值。
        /// </summary>
        /// <param name="className">算法类名</param>
        /// <param name="tcode">待加密的字符串</param>
        /// <returns>加密后的字节数组</returns>
        private byte[] ComputeHash(string className, string tcode)
        {
            byte[] bufRes = null;
            // 加载程序集
            Assembly asmby = Assembly.Load(@"mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089");
            Type myType = asmby.GetType("System.Security.Cryptography." + className, false, true);
            if (myType != null)
            {
                // 得到与Create方法有关的MethodInfo
                // GetMethod通过传入的Type数组的维数和类型来
                // 判断获取哪个重载。
                MethodInfo mdf=myType.GetMethod("Create",new Type[0]);
                if (mdf != null)
                {
                    object ob = null;
                    // 调用方法
                    ob = mdf.Invoke(null, null);
                    if (ob != null)
                    {
                        // 得到ComputeHash方法的MethodInfo
                        MethodInfo mfo = myType.GetMethod("ComputeHash", new Type[] { typeof(byte[]) });
                        if (mfo!=null)
                        {
                            // 调用方法
                            bufRes = (byte[])mfo.Invoke(ob, new object[]{
                                Encoding.Default.GetBytes(tcode)
                            });
                        }
                    }
                }
            }
            return bufRes;
        }


接着需要一个方法来把字节数组转为字符串。

        /// <summary>
        /// 把字节数组转换为十六进制字符串。
        /// </summary>
        /// <param name="bf"></param>
        /// <returns></returns>
        private string ByteToStr(byte[] bf)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in bf)
            {
                sb.Append(b.ToString("x2"));
            }
            return sb.ToString();
        }


然后,我们就可以在其它代码中使用了。

    public partial class b : Form
    {
        public b()
        {
            InitializeComponent();
            comboBox1.Items.Add("HMAC");
            comboBox1.Items.Add("MD5");
            comboBox1.Items.Add("SHA1");
            comboBox1.Items.Add("SHA256");
            comboBox1.Items.Add("SHA384");
            comboBox1.Items.Add("SHA512");
            comboBox1.Items.Add("RIPEMD160");
            comboBox1.DropDownStyle = ComboBoxStyle.DropDownList;
            comboBox1.SelectedIndex = 0;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (comboBox1.SelectedIndex == -1)
            {
                return;
            }
            try
            {
                byte[] bHash = ComputeHash(comboBox1.SelectedItem.ToString(), txtIn.Text);
                if (bHash != null)
                {
                    txtOut.Text = ByteToStr(bHash);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }


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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值