using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Cryptography;
using System.Text;
namespace rySafe
{
    /// <summary>
    /// MD5和SHA1操作类
    /// </summary>
    public class MD5Sha1
    {
        /// <summary>
        /// <para>计算文件MD5。</para>
        /// 通过MD5CryptoServiceProvider类中的ComputeHash方法直接传入一个FileStream类实现计算MD5
        /// 操作简单，代码少，调用即可
        /// </summary>
        /// <param name="path">文件地址</param>
        /// <returns>MD5Hash</returns>
        public static string GetFileMD5ByMD5CryptoService(string path)
        {
            if (!File.Exists(path))
            { return ""; }
            FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.Read);
            MD5CryptoServiceProvider md5Provider = new MD5CryptoServiceProvider();
            byte[] buffer = md5Provider.ComputeHash(fs);
            string resule = BitConverter.ToString(buffer);
            resule = resule.Replace("-", "");
            md5Provider.Clear();
            fs.Close();
            return resule;
        }

        /// <summary>
        /// <para>计算文件MD5。</para>
        /// 通过HashAlgorithm的TransformBlock方法对流进行叠加运算获得MD5
        /// 实现稍微复杂，但可使用与传输文件或接收文件时同步计算MD5值
        /// 可自定义缓冲区大小，计算速度较快
        /// </summary>
        /// <param name="path">文件地址</param>
        /// <returns>MD5Hash</returns>
        public static string GetFileMD5ByHashAlgorithm(string path)
        {
            try
            {
                if (!File.Exists(path))
                { return ""; }
                int bufferSize = 1024 * 16;//自定义缓冲区大小16K
                byte[] buffer = new byte[bufferSize];
                Stream inputStream = File.Open(path, FileMode.Open, FileAccess.Read, FileShare.Read);
                HashAlgorithm hashAlgorithm = new MD5CryptoServiceProvider();
                int readLength = 0;//每次读取长度
                var output = new byte[bufferSize];
                while ((readLength = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                {
                    //计算MD5
                    hashAlgorithm.TransformBlock(buffer, 0, readLength, output, 0);
                }
                //完成最后计算，必须调用(由于上一部循环已经完成所有运算，所以调用此方法时后面的两个参数都为0)
                hashAlgorithm.TransformFinalBlock(buffer, 0, 0);
                string md5 = BitConverter.ToString(hashAlgorithm.Hash);
                hashAlgorithm.Clear();
                inputStream.Close();
                md5 = md5.Replace("-", "");
                return md5;
            }
            catch { return ""; }
        }
        /// <summary>
        /// 获取MD5
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetMD5(string str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(str)))
            {
                sb.Append(b.ToString("X2"));
            }
            return sb.ToString().Trim();
        }
        /// <summary>
        /// 获取MD5
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetMD5(byte[] str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in System.Security.Cryptography.MD5.Create().ComputeHash(str))
            {
                sb.Append(b.ToString("X2"));
            }
            return sb.ToString().Trim();
        }
        /// <summary>
        /// 获取SHA1
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetSHA1(string str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in System.Security.Cryptography.SHA1.Create().ComputeHash(Encoding.UTF8.GetBytes(str)))
            {
                sb.Append(b.ToString("X2"));
            }
            return sb.ToString();
        }
        /// <summary>
        /// 获取SHA1
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public static string GetSHA1(byte[] str)
        {
            StringBuilder sb = new StringBuilder();
            foreach (byte b in System.Security.Cryptography.SHA1.Create().ComputeHash(str))
            {
                sb.Append(b.ToString("X2"));
            }
            return sb.ToString();
        }
        /// <summary>
        /// 获取HmacSHA1
        /// </summary>
        /// <param name="data"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public static string GetSHA1(string data, string pwd)
        {
            var myHMACSHA = new HMACSHA1(Encoding.UTF8.GetBytes(pwd));
            byte[] hash = myHMACSHA.ComputeHash(Encoding.UTF8.GetBytes(data));
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }
            return builder.ToString();
        }
        /// <summary>
        /// 获取SHA256
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string GetSHA256(string data)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(data);
            byte[] hash = SHA256Managed.Create().ComputeHash(bytes);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }
            return builder.ToString();
        }
        /// <summary>
        /// 获取HmacSHA256
        /// </summary>
        /// <param name="data"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public static string GetSHA256(string data, string pwd)
        {
            var myHMACSHA = new HMACSHA256(Encoding.UTF8.GetBytes(pwd));
            byte[] hash = myHMACSHA.ComputeHash(Encoding.UTF8.GetBytes(data));
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }
            return builder.ToString();
        }
        /// <summary>
        /// 获取SHA224
        /// </summary>
        /// <param name="str"></param>
        /// <returns></returns>
        public  string GetSHA224(string str)
        {
            SHA256 sha = new SHA256Managed();  // 用来计算 SHA256 哈希值
            UTF8Encoding uen = new UTF8Encoding();  // 用来把char[]转换成byte[]
            byte[] bytestr = uen.GetBytes(str.ToCharArray());
            sha.ComputeHash(bytestr);  // 计算哈希值
            String sha224 = "";
            for (int i = 0; i < 28; ++i)
            {
                int dec = int.Parse(sha.Hash.GetValue(i).ToString());   // 十进制
                String bin = Convert.ToString(dec, 2).PadLeft(8, '0');  // 转成二进制数，是8位的，不足8位前面补0
                sha224 += bin;
            }
            return sha224;
        }
        /// <summary>
        /// 获取SHA512
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static string GetSHA512(string data)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(data);
            byte[] hash = SHA512.Create().ComputeHash(bytes);
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }
            return builder.ToString();
        }
        /// <summary>
        /// 获取HmacSHA512
        /// </summary>
        /// <param name="data"></param>
        /// <param name="pwd"></param>
        /// <returns></returns>
        public static string GetSHA512(string data, string pwd)
        {
            var myHMACSHA = new HMACSHA512(Encoding.UTF8.GetBytes(pwd));
            byte[] hash = myHMACSHA.ComputeHash(Encoding.UTF8.GetBytes(data));
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                builder.Append(hash[i].ToString("X2"));
            }
            return builder.ToString();
        }
    }
}
