C# MD5

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();
        }
    }
}

結果:
安全

wKioL1mAYzaTsFHOAADUdecifV4000.png-wh_50

從測試代碼看出 , 咱們用32位MD5加密過的密文和用64位MD5加密過的密文是徹底不同的,這點要注意.ide

好比 : 你存的用戶的密碼是用32位MD5加密過的,而對比密碼卻用64位的,那就很尷尬了.測試


二,關於文件驗證ui

①,測試準備編碼

咱們先在Debug目錄放2個文件:加密

wKiom1mAZPLR2amHAAAjT6jWzng108.png-wh_50

關於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();
        }
    }
}

結果:

wKioL1mAZnKQqLT6AABo7cbQKvM815.png-wh_50

確實是 , checkmd5.xml沒有關於Aonaufly.xml的記錄,以下圖

wKiom1mAZtexGLZWAAAdi4OrMaA324.png-wh_50

好,咱們記錄一條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文件的改變而改變

結果以下:

wKioL1mAaKTRRl9EAAAriHWBCYU173.png-wh_50

注意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();
        }
    }
}

獲得結果以下:

wKiom1mAaX_Q6V71AACdYQ9groE559.png-wh_50


而當咱們修改了一個Aonaufly.xml , 以下:

wKioL1mAajjhxhbEAAB8gaDr2Z8612.png-wh_50

咱們仍是以no.3(如上)代碼測試 . 結果以下:

wKiom1mAaqixx5LYAADP2cEpTjM711.png-wh_50

在文件簽名的應用中,在程序每一個正式的版本中打一個MD5碼,監聽配置文件的篡改,保證安全.

相關文章
相關標籤/搜索