MD5加密在由于具备加密的不可逆性,因此在密码加密,以及文件验证有很大的应用.在密码加密方面,若是在数据库中保存明文密码,将是很是危险的.若是密码是MD5加密过得,就会安全的多node
可是用MD5加密过的明文密码,由于是不能逆向还原出明文的.好处是:DBA,开发人员最多只知道你的MD5加密过的密码,而不知道正真的密码,坏处是一旦你本身把密码忘了,那就只能经过邮件等方式更换密码了.数据库
好了先上一段MD5的核心类:c#
using System; using System.Text; using System.Security.Cryptography; using System.IO; using System.Xml; namespace MD5Lib { /// <summary> /// MD5加密及验证 /// </summary> public sealed class MD5Helper { /// <summary> /// 得到64位的MD5加密 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string GetMD5_64(string input) { MD5 md5 = MD5.Create(); // 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(input)); return Convert.ToBase64String(s); } /// <summary> /// 得到32位的MD5加密 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string GetMD5_32(string input) { System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] data = md5.ComputeHash(System.Text.Encoding.Default.GetBytes(input)); StringBuilder sb = new StringBuilder(); for (int i = 0; i < data.Length; i++) { sb.Append(data[i].ToString("x2")); } return sb.ToString(); } /// <summary> /// 得到16位的MD5加密 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string GetMD5_16(string input) { return GetMD5_32(input).Substring(8, 16); } /// <summary> /// 得到8位的MD5加密 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string GetMD5_8(string input) { return GetMD5_32(input).Substring(8, 8); } /// <summary> /// 得到4位的MD5加密 /// </summary> /// <param name="input"></param> /// <returns></returns> public static string GetMD5_4(string input) { return GetMD5_32(input).Substring(8, 4); } public static string MD5EncryptHash(String input) { MD5 md5 = new MD5CryptoServiceProvider(); //the GetBytes method returns byte array equavalent of a string byte[] res = md5.ComputeHash(Encoding.Default.GetBytes(input), 0, input.Length); char[] temp = new char[res.Length]; //copy to a char array which can be passed to a String constructor Array.Copy(res, temp, res.Length); //return the result as a string return new String(temp); } //对文件添加MD5标签及验证 #region MD5签名验证 /// <summary> /// 对给定文件路径的文件加上标签(若是文件已经更改,则更新配置的MD5值) /// </summary> /// <param name="path">要加密的文件的路径</param> /// <param name="md5_conf_path">加密的密文保存文件地址(自动生成配置)</param> /// <returns>标签的值</returns> public static bool AddMD5(string path , string md5_conf_path) { bool IsNeed = true; if (CheckMD5(path,md5_conf_path)) //已进行MD5处理 IsNeed = false; try { if (IsNeed) { FileStream fsread = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] md5File = new byte[fsread.Length]; fsread.Read(md5File, 0, (int)fsread.Length); // 将文件流读取到Buffer中 fsread.Close(); string result = MD5Buffer(md5File, 0, md5File.Length); // 对Buffer中的字节内容算MD5 Boolean is_exist = false; XmlDocument doc = new XmlDocument(); doc.Load(md5_conf_path); XmlNodeList node_path = doc.SelectNodes("data/path"); foreach (XmlNode item in node_path) { if (item.Attributes["file"].InnerText == path) { is_exist = true; item.Attributes["md5"].InnerText = result;//修改file的验证码 doc.Save(md5_conf_path);//保存到配置 break; } } if (!is_exist) { //加入MD5验证配置 XmlElement root = doc.DocumentElement;//获取根节点 XmlElement tagOuter = doc.CreateElement("path"); tagOuter.SetAttribute("file", path); tagOuter.SetAttribute("md5", result); root.AppendChild(tagOuter); doc.Save(md5_conf_path);//保存到配置 } } } catch { return false; } return true; } /// <summary> /// 对给定路径的文件进行验证 /// </summary> /// <param name="path">md5加密的文件</param> /// <param name="md5_conf_path">加密的密文保存文件地址</param> /// <returns>是否加了标签或是否标签值与内容值一致</returns> public static bool CheckMD5(string path, string md5_conf_path) { try { FileStream get_file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read); byte[] md5File = new byte[get_file.Length]; // 读入文件 get_file.Read(md5File, 0, (int)get_file.Length); get_file.Close(); Boolean is_exist = false; XmlDocument doc = new XmlDocument(); doc.Load(md5_conf_path); XmlNodeList node_path = doc.SelectNodes("data/path"); string md5 = string.Empty; foreach (XmlNode item in node_path) { if (item.Attributes["file"].InnerText == path) { is_exist = true; md5 = item.Attributes["md5"].InnerText; break; } } if (!is_exist) return false;//没有配置返回false string result = MD5Buffer(md5File, 0, md5File.Length);//计算path的MD5值,用于与配置文件里面的MD5进行对比 return result == md5; } catch { return false; } } /// <summary> /// 是否存在文件的MD5密码的配置 /// </summary> /// <param name="path">文件路径</param> /// <param name="md5_conf_path">配置路径</param> /// <returns></returns> public static Boolean Is_Exist(string path, string md5_conf_path) { XmlDocument doc = new XmlDocument(); doc.Load(md5_conf_path); XmlNodeList node_path = doc.SelectNodes("data/path"); foreach (XmlNode item in node_path) { if (item.Attributes["file"].InnerText == path) { return true; } } return false; } /// <summary> /// 计算文件的MD5值 /// </summary> /// <param name="MD5File">MD5签名文件字符数组</param> /// <param name="index">计算起始位置</param> /// <param name="count">计算终止位置</param> /// <returns>计算结果</returns> private static string MD5Buffer(byte[] MD5File, int index, int count) { System.Security.Cryptography.MD5CryptoServiceProvider get_md5 = new System.Security.Cryptography.MD5CryptoServiceProvider(); byte[] hash_byte = get_md5.ComputeHash(MD5File, index, count); string result = System.BitConverter.ToString(hash_byte); result = result.Replace("-", ""); return result; } #endregion } }
一,先测试Password(密码)加密:数组
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MD5Lib; namespace MD5Demo { class Program { static void Main(string[] args) { string my_password = "Aonaufly-%~ss"; Console.WriteLine("个人密码 : {0} ", my_password); //使用32MD5加密 string md5_32_miwen = MD5Helper.GetMD5_32(my_password); Console.WriteLine("对密码 : {0} 加密后 MD5密文 : {1}", my_password , md5_32_miwen); if (md5_32_miwen == MD5Helper.GetMD5_64(my_password)) { Console.WriteLine("密码验证经过"); } else { Console.WriteLine("密码验证未经过 -- 32为加密和64位加密的密文是不同的"); Console.WriteLine("==========================================="); if (md5_32_miwen == MD5Helper.GetMD5_32(my_password)) { Console.WriteLine("密码验证经过"); } } Console.Read(); } } }
结果:
安全
从测试代码看出 , 咱们用32位MD5加密过的密文和用64位MD5加密过的密文是彻底不同的,这点要注意.ide
好比 : 你存的用户的密码是用32位MD5加密过的,而对比密码却用64位的,那就很尴尬了.测试
二,关于文件验证ui
①,测试准备编码
咱们先在Debug目录放2个文件:加密
关于Aonaufly.xml(程序游戏当中进行使用) , 以下:
<?xml version="1.0" encoding="utf-8" ?> <data> <img name="offline_Settlement1" res="uiimg/res/img/offline_other/js_taitou_1.png"/> <img name="offline_Settlement2" res="uiimg/res/img/offline_other/js_taitou_2.png"/> <img name="offline_Settlement3" res="uiimg/res/img/offline_other/jjcg_ditu.png"/> <img name="offline_Settlement4" res="uiimg/res/img/offline_other/tanchuang.png"/> <img name="offline_Settlement5" res="uiimg/res/img/offline_other/lose.png"/> <img name="offline_Settlement6" res="uiimg/res/img/offline_other/win.png"/> </data>
关于checkmd5.xml(用于验证程序游戏中的配置是否安全)
<?xml version="1.0" encoding="utf-8"?> <data> </data>
咱们来看测试代码 no.1 , 以下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MD5Lib; namespace MD5Demo { class Program { static void Main(string[] args) { Console.WriteLine("MD5签名验证======================================"); string txt_path = @"Aonaufly.xml";//测试文件(为此文件生成MD5码) string txt_md5_conf = @"checkmd5.xml";//全部须要生成MD5码的文件的MD5码保存在此文件中 //MD5Helper.AddMD5(txt_path, txt_md5_conf); //对给定文件路径的文件加上标签 - 成功 if (MD5Helper.CheckMD5(txt_path, txt_md5_conf)) { Console.WriteLine("{0} 没有被篡改,能够放心使用" , txt_path); } else { if (MD5Helper.Is_Exist(txt_path, txt_md5_conf)) { Console.WriteLine("{0} 已经被篡改,请当心使用", txt_path); } else { Console.WriteLine("{0}中不存在文件{1}的MD5的配置信息,请从新生成!!!", txt_md5_conf, txt_path); } } Console.Read(); } } }
结果:
确实是 , checkmd5.xml没有关于Aonaufly.xml的记录,以下图
好,咱们记录一条Aoanufly.xml的MD5信息,代码以下: no.2
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MD5Lib; namespace MD5Demo { class Program { static void Main(string[] args) { Console.WriteLine("MD5签名验证======================================"); string txt_path = @"Aonaufly.xml";//测试文件(为此文件生成MD5码) string txt_md5_conf = @"checkmd5.xml";//全部须要生成MD5码的文件的MD5码保存在此文件中 MD5Helper.AddMD5(txt_path, txt_md5_conf); Console.Read(); } } }
MD5Helper.AddMD5(txt_path, txt_md5_conf);
将txt_path文件的md5码记录到txt_md5_conf文件中,注意,如txt_md5_conf中无关于txt_path文件的md5的记录则作添加操做,若是有(①,MD5没有改变则不做任何错误,②,MD5已变动改其记录的MD5值)
注意MD5会由于txt_path文件的改变而改变
结果以下:
注意file为Aonaufly.xml的路径,是path
咱们不改变Aonaufly.xml的内容,作测试 no.3,以下
using System; using System.Collections.Generic; using System.Linq; using System.Text; using MD5Lib; namespace MD5Demo { class Program { static void Main(string[] args) { Console.WriteLine("MD5签名验证======================================"); string txt_path = @"Aonaufly.xml";//测试文件(为此文件生成MD5码) string txt_md5_conf = @"checkmd5.xml";//全部须要生成MD5码的文件的MD5码保存在此文件中 //MD5Helper.AddMD5(txt_path, txt_md5_conf); //对给定文件路径的文件加上标签 - 成功 if (MD5Helper.CheckMD5(txt_path, txt_md5_conf)) { Console.WriteLine("{0} 没有被篡改,能够放心使用" , txt_path); } else { if (MD5Helper.Is_Exist(txt_path, txt_md5_conf)) { Console.WriteLine("{0} 已经被篡改,请当心使用", txt_path); } else { Console.WriteLine("{0}中不存在文件{1}的MD5的配置信息,请从新生成!!!", txt_md5_conf, txt_path); } } Console.Read(); } } }
获得结果以下:
而当咱们修改了一个Aonaufly.xml , 以下:
咱们仍是以no.3(如上)代码测试 . 结果以下:
在文件签名的应用中,在程序每一个正式的版本中打一个MD5码,监听配置文件的篡改,保证安全.