C#实现Hash应用全解
1、引言
HASH是根据文件内容的数据通过逻辑运算得到的数值, 不同的文件(即使是相同的文件名)得到的HASH值是不同的。

通过一定的哈希算法(典型的有MD5,SHA-1等),将一段较长的数据映射为较短小的数据,这段小数据就是大数据的哈希值。他最大的特点就是唯一性,一旦大数据发生了变化,哪怕是一个微小的变化,他的哈希值也会发生变化。类似于DNA,既然是DNA,那就保证了没有两个数据的哈希值是完全相同的。
哈希值的作用:哈希值,即HASH值,是通过对文件内容进行加密运算得到的一组二进制值,主要用途是用于文件校验或签名。正是因为这样的特点,它常常用来判断两个文件是否相同。
比如,从网络上下载某个文件,只要把这个文件原来的哈希值同下载后得到的文件的哈希值进行对比,如果相同则表示两个文件完全一致,下载过程没有损坏文件。而如果不一致,则表明下载得到的文件跟原来的文件不同,文件在下载过程中受到了损坏。Hash的应用非常广泛,主要应用于:
1.文件校验
我们比较熟悉的校验算法有奇偶校验和CRC校验,这2种校验并没有抗数据篡改的能力,它们一定程度上能检测并纠正数据传输中的信道误码,但却不能防止对数据的恶意破坏。
MD5Hash算法的”数字指纹”特性,使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法,不少Unix系统有提供计算md5checksum的命令。
2. 唯一标识
现在有十万个文件, 给你一个文件, 要你在这十万个文件中查找是否存在. 一个很笨的办法就是把每一文件都拿出来, 然后按照二进制串一一进行对比. 但是这个操作注定是比较费时的。可以用哈希算法对文件进行计算, 然后比较哈希值是否相同。 因为存在哈希冲突的情况, 你可以在相同哈希值的文件再进行二进制串比较.
3. 数字签名
Hash算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢,所以在数字签名协议中,单向散列函数扮演了一个重要的角色。对Hash值,又称”数字摘要”进行数字签名,在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点。
4. 哈希表
在哈希表中使用哈希函数已经并不陌生了, 不再赘述。
5. 负载均衡
比如说, 现在又多台服务器, 来了一个请求, 如何确定这个请求应该路由到哪个路由器呢?当然, 必须确保相同的请求经过路由到达同一个服务器. 一种办法就是保存一张路由关系的表, 比如客户端IP和服务器编号的映射, 但是如果客户端很多, 势必查找的时间会很长。 这时, 可以将客户端的唯一标识信息(如:IP、username等)进行哈希计算, 然后与服务器个数取模, 得到的就是服务器的编号。
6. 分布式存储
当我们有大量数据时, 为了提高读取与写入的速度, 一般会选择将数据存储到多个服务器。 决定将文件存储到哪台服务器, 就可以通过哈希算法取模的操作来得到。
但是, 如果数据多了, 要增加服务器了, 问题就来了, 比如原来是10台服务器, 现在变成15台了, 那么原来哈希值为16的文件被分配到编号6的服务器, 现在被分配到编号1的服务器, 也就意味着所有文件都要重新计算哈希值并重新非陪服务器进行存储。 一致性哈希就是这个用途。

2、C#开发用于计算文件Hash的辅助类HashHelper
在C#中,数据的Hash以MD5或SHA1的方式实现,MD5与SHA1都是Hash算法,MD5输出是128位的,SHA1输出是160位的,MD5比SHA1快,SHA1比MD5强度高。
2.1、SHA-1和MD5的比较
因为二者均由MD4导出,SHA-1和MD5彼此很相似。相应的,他们的强度和其他特性也是相似,但还有以下几点不同:
1)对强行攻击的安全性:最显著和最重要的区别是SHA-1摘要比MD5摘要长32 位。使用强行技术,产生任何一个报文使其摘要等于给定报摘要的难度对MD5是2128数量级的操作,而对SHA-1则是2160数量级的操作。这样,SHA-1对强行攻击有更大的强度。
2)对密码分析的安全性:由于MD5的设计,易受密码分析的攻击,SHA-1显得不易受这样的攻击。
3)速度:在相同的硬件上,SHA-1的运行速度比MD5慢。
2.2、SHA-1和MD5在C#中的实现
/// <summary>
/// Hash辅助类
/// </summary>
public class HashHelper
{
/// <summary>
/// 计算文件的 MD5 值
/// </summary>
/// <param name="fileName">要计算 MD5 值的文件名和路径</param>
/// <returns>MD5 值16进制字符串</returns>
public static string MD5File(string fileName)
{
return HashFile(fileName, "md5");
}
/// <summary>
/// 计算文件的 sha1 值
/// </summary>
/// <param name="fileName">要计算 sha1 值的文件名和路径</param>
/// <returns>sha1 值16进制字符串</returns>
public static string SHA1File(string fileName)
{
return HashFile(fileName, "sha1");
}
/// <summary>
/// 计算文件的哈希值
/// </summary>
/// <param name="fileName">要计算哈希值的文件名和路径</param>
/// <param name="algName">算法:sha1,md5</param>
/// <returns>哈希值16进制字符串</returns>
private static string HashFile(string fileName, string algName)
{
if (!System.IO.File.Exists(fileName))
{
return string.Empty;
}
System.IO.FileStream fs = new System.IO.FileStream(fileName, System.IO.FileMode.Open, System.IO.FileAccess.Read);
byte[] hashBytes = HashData(fs, algName);
fs.Close();
return ByteArrayToHexString(hashBytes);
}
/// <summary>
/// 计算哈希值
/// </summary>
/// <param name="stream">要计算哈希值的 Stream</param>
/// <param name="algName">算法:sha1,md5</param>
/// <returns>哈希值字节数组</returns>
private static byte[] HashData(System.IO.Stream stream, string algName)
{
System.Security.Cryptography.HashAlgorithm algorithm;
if (algName == null)
{
throw new ArgumentNullException("algName 不能为 null");
}
if (string.Compare(algName, "sha1", true) == 0)
{
algorithm = System.Security.Cryptography.SHA1.Create();
}
else
{
if (string.Compare(algName, "md5", true) != 0)
{
throw new Exception("algName 只能使用 sha1 或 md5");
}
algorithm = System.Security.Cryptography.MD5.Create();
}
return algorithm.ComputeHash(stream);
}
/// <summary>
/// 字节数组转换为16进制表示的字符串
/// </summary>
private static string ByteArrayToHexString(byte[] buf)
{
return BitConverter.ToString(buf).Replace("-", "");
}
}
2.2、SHA-1和MD5在C#中的实现的测试用例
[TestClass]
public class HashHelperUnitTest
{
[TestMethod]
public void TestMethod1()
{
string fileName = @"D:\TempTest\RDIFramework.BizLogic.dll";
Assert.AreEqual(0, 0);
//01.计算文件的 MD5 值
Console.WriteLine(string.Format("计算文件的 MD5 值:{0}", HashHelper.MD5File(fileName)));
//02.计算文件的 sha1 值
Console.WriteLine(string.Format("计算文件的 sha1 值:{0}", HashHelper.SHA1File(fileName)));
}
}

参考文章
框架相关
一路走来数个年头,感谢RDIFramework.NET框架的支持者与使用者,大家可以通过下面的地址了解详情。
RDIFramework.NET官方网站:http://www.rdiframework.net/
RDIFramework.NET官方博客:http://blog.rdiframework.net/
同时需要说明的,以后的所有技术文章以官方网站为准,欢迎大家收藏!
RDIFramework.NET框架由海南国思软件科技有限公司专业团队长期打造、一直在更新、一直在升级,请放心使用!
欢迎关注RDIFramework.net框架官方公众微信(微信号:guosisoft),及时了解最新动态。
扫描二维码立即关注

C#实现Hash应用全解的更多相关文章
- [转帖]Linux学习笔记之rpm包管理功能全解
Linux学习笔记之rpm包管理功能全解 https://www.cnblogs.com/JetpropelledSnake/p/11177277.html rpm 的管理命令 之前学习过 yum 的 ...
- redis全解
Redis全解 1.什么是Redis? Redis本质上是一个Key-Value类型的内存数据库,很像memcached,整个数据库统统加载在内存当中进行操作,定期通过异步操作把数据库数据flush到 ...
- 易全解token获取
//易全解app string strClientID = "2016061711434943493606"; string str ...
- IOS-UITextField-全解
IOS-UITextField-全解 //初始化textfield并设置位置及大小 UITextField *text = [[UITextField alloc]initWithFrame: ...
- 什么是JavaScript闭包终极全解之一——基础概念
本文转自:http://www.cnblogs.com/richaaaard/p/4755021.html 什么是JavaScript闭包终极全解之一——基础概念 “闭包是JavaScript的一大谜 ...
- Sql Server函数全解<五>之系统函数
原文:Sql Server函数全解<五>之系统函数 系统信息包括当前使用的数据库名称,主机名,系统错误消息以及用户名称等内容.使用SQL SERVER中的系统函数可以在需要的时候获取这些 ...
- Sql Server函数全解<四>日期和时间函数
原文:Sql Server函数全解<四>日期和时间函数 日期和时间函数主要用来处理日期和时间值,本篇主要介绍各种日期和时间函数的功能和用法,一般的日期函数除了使用date类型的参数外, ...
- 九度oj题目&吉大考研11年机试题全解
九度oj题目(吉大考研11年机试题全解) 吉大考研机试2011年题目: 题目一(jobdu1105:字符串的反码). http://ac.jobdu.com/problem.php?pid=11 ...
- js系列教程2-对象、构造函数、对象属性全解
全栈工程师开发手册 (作者:栾鹏) 快捷链接: js系列教程1-数组操作全解 js系列教程2-对象和属性全解 js系列教程3-字符串和正则全解 js系列教程4-函数与参数全解 js系列教程5-容器和算 ...
随机推荐
- Python笔记【7】_反射getattr&hasattr&setattr&delattr
Lesson0402_GetatrrWebsite.py #!/usr/bin/env/python #-*-coding:utf-8-*- #Author:LingChongShi #查看源码Ctr ...
- lower_bound 和 upper_bound 功能和用法
以前用这两个函数的时候,简单看了几句别人的博客,记住了大概,用的时候每用一次就弄混一次,相当难受,今天对照着这两个函数的源码和自己的尝试发现:其实这两个函数只能用于 "升序" 序列 ...
- 关于svn服务部署方案
本文只记录我的笔记 首先, 我是个懒人, 写好了shell, 直接上传把 安装包:SvnPackages-chenglee 第一, 无非就是搞掂依赖这一块 #********************* ...
- Maven下载Jar包(bat脚本)
1.创建一个bat文件叫download.bat 2.里面写入以下代码 call mvn -f pom.xml dependency:copy-dependencies 3.创建pom.xml文件 4 ...
- Codeforces Gym101257F:Islands II(求割点+思维)
http://codeforces.com/gym/101257/problem/F 题意:给出一个n*m的地图,上面相同数字的代表一个国家,问对于每个国家有多少个国家在它内部(即被包围).例如第一个 ...
- SQL Server 2016 + AlwaysOn 无域集群
目录 AlwaysOn 搭建 WSFC 配置计算机的 DNS 后缀 安装故障转移集群 验证集群 创建集群 创建文件共享见证 配置 AlwaysOn 新建可用性组 创建侦听器 可读副本的负载均衡 主角色 ...
- 通过Spring整合hibernate并进行单元测试(详细)
一. 没有基础hibernate基础的可以点击这里 ---------->ORM----hibernate入门Demo(无敌详细版) 这里我就不详细介绍了.. 二. hibernat.cfg.x ...
- Linux soft lockup 和 hard lockup
一. 整体介绍 soft lockup:检测调度异常, 一般是驱动禁止调度或者阻塞比如while(1), 导致无法调度其他线程, 需要注意的是, 应用程序while(1)不会影响其调度, 只要有更高的 ...
- 【素数的判定-从暴力到高效】-C++
今天我们来谈一谈素数的判定. 对于每一个OIer来说,在漫长的练习过程中,素数不可能不在我们的眼中出现,那么判定素数也是每一个OIer应该掌握的操作,那么我们今天来分享几种从暴力到高效的判定方法. 1 ...
- Python 3.5学习笔记(第二章)
本章内容 1.模块 2.数据类型与数据运算 3.进制 4.byte 与 string 的互相转换 5.列表 6.元组 7.字符串操作 8.字典 一.模块 Python 把某些常用的定义存放在文件中,为 ...