计算文件Hash(SHA1、MD5等)
HashAlgorithm类支持数据块的Hash运算:对数据前面块通过TransformBlock方法计算,最后一块通过TransformFinalBlock方法计算,结果通过Hash属性获得,便可完成整个Hash过程。对于一个数据流(如文件流),可以利用这个办法,提供Hash的计算进度。下面是一个不带计算进度的使用的使用TransformBlock方式的代码。
using System;
using System.IO;
using System.Security.Cryptography;namespace SHA1_and_MD5
{public static class Algorithm{/// <summary>/// 计算文件的Hash值/// </summary>/// <param name="fileName">文件名</param>/// <param name="hashName">Hash名</param>/// <returns>Hash的文本结果</returns>public static string ComputeHash(string fileName, string hashName){var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read);var value = Hash(fs, hashName);fs.Close();return BitConverter.ToString(value).Replace("-", "").ToLower();}/// <summary>/// 计算流的Hash值/// </summary>/// <param name="stream">流</param>/// <param name="hashName">Hash名</param>/// <returns>Hash结果</returns>public static byte[] ComputeHash(Stream stream, string hashName){const int bufferSize = 4096; //0x1000var hash = HashAlgorithm.Create(hashName);int num;var buffer = new byte[bufferSize];do{num = stream.Read(buffer, 0, bufferSize);if (num == bufferSize){hash.TransformBlock(buffer, 0, num, buffer, 0);}else if (stream.Length == stream.Position){hash.TransformFinalBlock(buffer, 0, num);}else if (num > 0){//当 0 < num < bufferSize 的情况var buffer2 = new byte[num];Buffer.BlockCopy(buffer, 0, buffer2, 0, num);hash.TransformBlock(buffer2, 0, num, buffer2, 0);}} while (num > 0);return hash.Hash;}}
}
代码中hashName参数可以为以下值:
hashName参考:http://msdn.microsoft.com/zh-cn/library/wet69s13(VS.90).aspx | |
简单名称 | 算法实现 |
SHA | SHA1CryptoServiceProvider |
SHA1 | SHA1CryptoServiceProvider |
System.Security.Cryptography.SHA1 | SHA1CryptoServiceProvider |
System.Security.Cryptography.HashAlgorithm | SHA1CryptoServiceProvider |
MD5 | MD5CryptoServiceProvider |
System.Security.Cryptography.MD5 | MD5CryptoServiceProvider |
SHA256 | SHA256Managed |
SHA-256 | SHA256Managed |
System.Security.Cryptography.SHA256 | SHA256Managed |
SHA384 | SHA384Managed |
SHA-384 | SHA384Managed |
System.Security.Cryptography.SHA384 | SHA384Managed |
SHA512 | SHA512Managed |
SHA-512 | SHA512Managed |
System.Security.Cryptography.SHA512 | SHA512Managed |
比如,想计算系统记事本的sha1和md5,可以这样调用:
MessageBox.Show(Algorithm.ComputeHash(@"c:/windows/notepad.exe", "SHA1") + Environment.NewLine +Algorithm.ComputeHash(@"c:/windows/notepad.exe", "MD5"));
接下来,对上面的代码进行修改,加入计算时回调HashingCallback和结束时回调EndCallback,在进行ComputeHash计算时,do-while中每处理完成一组数据,执行一次HashingCallback的回调函数,全部计算完成后执行EndCallback的回调函数。为了在计算过程中取消计算,增加Stop方法,它将_cancel字段设置为true,而ComputeHash方法的do-while条件增加对_cancel的判断。回调函数的参数都包含了一个可传递的object类型的State属性,HashingCallback委托的HashingState参数,目的给出计算Hash的进度,EndCallback的EndState属性,目的通知计算结束,给出是否为中途取消而结束的。而最后的Hash结果通过Hash属性获得。另外,重载ToString方法,直接输出字符串的Hash结果。
于是,我们的代码改写成可实例化的类:
using System;
using System.IO;
using System.Security.Cryptography;namespace SHA1_and_MD5
{public class MyHashAlgorithm{#region Delegates/// <summary>/// 完成Hash计算的回调/// </summary>public delegate void EndCallback(EndState endState);/// <summary>/// 进行Hash计算时的回调/// </summary>public delegate void HashingCallback(HashingState hashingState);#endregionprivate bool _cancel; //取消计算/// <summary>/// 获得Hash结果/// </summary>public byte[] Hash { get; private set; }/// <summary>/// 输出Hash结果的字符串版本/// </summary>/// <returns></returns>public override string ToString(){return Hash != null ? BitConverter.ToString(Hash).Replace("-", "").ToLower() : "";}/// <summary>/// 停止计算/// </summary>public void Stop(){_cancel = true;}/// <summary>/// 计算文件的Hash值/// </summary>/// <param name="fileName">文件名</param>/// <param name="hashName">Hash名</param>/// <param name="hashingCallback">进度回调函数</param>/// <param name="endCallback">结束计算的回调函数</param>/// <param name="state">传递给回调的参数</param>public void ComputeHash(string fileName, string hashName, HashingCallback hashingCallback,EndCallback endCallback, object state){using(var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.Read)){ComputeHash(fs, hashName, hashingCallback, endCallback, state);}}/// <summary>/// 计算流的Hash值/// </summary>/// <param name="stream">流</param>/// <param name="hashName">Hash名</param>/// <param name="hashingCallback">进度回调函数</param>/// <param name="endCallback">结束计算的回调函数</param>/// <param name="state">传递给回调的参数</param>public void ComputeHash(Stream stream, string hashName, HashingCallback hashingCallback, EndCallback endCallback,object state){const int bufferSize = 4096; //0x1000Hash = null;_cancel = false;bool nullHashingCallback = hashingCallback == null; //未指定计算时的回调long bytesRead = 0L; //已经完成的数据long totalBytesLength = stream.Length;HashAlgorithm hash = HashAlgorithm.Create(hashName);int num;var buffer = new byte[bufferSize];do{num = stream.Read(buffer, 0, bufferSize);if (num == bufferSize){hash.TransformBlock(buffer, 0, num, buffer, 0);}else if (totalBytesLength == stream.Position){hash.TransformFinalBlock(buffer, 0, num);}else if (num > 0){var buffer2 = new byte[num];Buffer.BlockCopy(buffer, 0, buffer2, 0, num);hash.TransformBlock(buffer2, 0, num, buffer2, 0);}if (num <= 0 || nullHashingCallback) continue;bytesRead += num;hashingCallback(new HashingState(bytesRead, totalBytesLength, state)); //执行计算时回调} while (num > 0 && !_cancel);Hash = _cancel ? new byte[0] : hash.Hash; //获得计算结果if (endCallback != null) endCallback(new EndState(_cancel, state)); //执行结束回调}#region Nested type: EndState/// <summary>/// 为EndCallback提供数据/// </summary>public class EndState{internal EndState(bool isCancel, object state){IsCancel = isCancel;State = state;}/// <summary>/// 是否取消退出的/// </summary>public bool IsCancel { get; private set; }/// <summary>/// 获得传递的参数/// </summary>public object State { get; private set; }}#endregion#region Nested type: HashingState/// <summary>/// 为HashingCallback提供数据/// </summary>public class HashingState{internal HashingState(long byteRead, long totalBytesLength, object state){BytesRead = byteRead;TotalBytesLength = totalBytesLength;State = state;}/// <summary>/// 获得已经计算完成的字节数/// </summary>public long BytesRead { get; private set; }/// <summary>/// 获得总字节数/// </summary>public long TotalBytesLength { get; private set; }/// <summary>/// 获得传递的参数/// </summary>public object State { get; private set; }}#endregion}
}
为了实现多线程支持,在调用时请使用Thread类实现。
var t =new Thread(() =>hasher.ComputeHash(@"D:/useful/ISO/VS2008SP1CHSX1512981.iso", "SHA1",hashingState => UpdateProgress(hashingState.BytesRead, hashingState.TotalBytesLength),endState => Finish(endState.IsCancel), null)){Name = "ComputeHash",IsBackground = true}; t.Start();
--
感谢uking09检查代码中的BUG。
计算文件Hash(SHA1、MD5等)相关推荐
- md5sum 命令 – 计算文件内容的 md5 值
md5sum 命令的功能是用于计算文件内容的 md5 值,进而比较两个文件相同与否.md5 值是一个128位的二进制数据,转换成16进制则是32位. 用户可以通过此命令对文件内容进行汇总并计算出一个 ...
- js快速计算文件hash值
1. 通过 requestIdleCallback or spark-md5利用浏览器空闲时间切片计算文件hash值: requestIdleCallback简介: window.requestIdl ...
- JavaScript计算文件Hash值(sha1 sha 256 md5)
一.引入外部库CryptoJS(简单) 1.字符串Hash <!DOCTYPE html> <html> <head><title>Hash算法< ...
- html5计算文件hash,spark-md5生成hash码,spark-md5计算大文件hash码实现断点续传
spark-md5import SparkMD5 from 'spark-md5'; var hexHash = SparkMD5.hash('Hi there'); // hex ha ...
- vue 计算文件hash值_vue项目打包文件增加hash值
vue项目打包文件增加hash值 vue-cli2项目 修改vue项目根目录下的 build/webpack.prod.conf.js文件 js文件: output: { path: config.b ...
- vue 计算文件hash值_vue的hash值原理,也是table切换。
.pages>div{display: none;} aaa bbb cccc 首页 关于我的页面 用户中心 //hash 和页面一一对应起来 //router 配置 var router = ...
- 【转】Java计算文件的hash值
原文地址:http://blog.csdn.net/qq_25646191/article/details/78863110 如何知道一个文件是否改变了呢?当然是用比较文件hash值的方法,文件has ...
- Java计算文件的hash值
如何知道一个文件是否改变了呢?当然是用比较文件hash值的方法,文件hash又叫文件签名,文件中哪怕一个bit位被改变了,文件hash就会不同. 比较常用的文件hash算法有MD5和SHA-1. 我用 ...
- sh256sum、xxd、base64联合计算文件的hash
计算文件hash值并进行base64编码 # 计算文件的sha256哈西值 $ sha256sum filename f3b6d97538bf435399529405f5b5e88a81911d043 ...
最新文章
- ES6新增的let与const
- NoSql数据库使用半年后在设计上面的一些心得
- 华为MAC Flapping , MAC的漂移
- 完整议程、重磅嘉宾公布,第四范式AI新品发布会持续报名中
- 保存光谱曲线出现问题_直读光谱仪计量周期-这家好【博越仪器】
- 在SAP UI5应用里使用jQuery.ajax读取数据并显示在页面上
- code blocks c语言,Code Blocks安装与使用图文教程(使用Code::Blocks编写C语言程序)...
- linux祖先进程,Linux下的几种特殊进程
- 创建一个 Git 版本库
- JAVA 即时网络通信我的服务器
- 引用网易等相册的图片出现防盗链怎么办呢?看这里就迎刃而解!(转贴)
- git21天打卡Day1-linux下安装git
- 最新IOS审核被拒原因TOP10 | 附带解决方法
- FileStream:The process cannot access the file because it is being used by another process
- GoogleNet家族
- 大一计算机word排版试题,武汉大学大一计算机作业word排版
- 【UE4笔记】Collision碰撞
- 阿里云注册账号、购买云服务器、搭建网站全流程(图文教程)
- 【Android】RecycleView简单仿漫画APP图片相关样式
- Android基础——RecycleView
热门文章
- 跟着cryptokitties(以太坊云养猫)学写智能合约(上)
- 关于正则表达式的复习与总结
- 计算机右击管理在哪,电脑权限管理在哪里
- python写梦幻西游手游脚本辅助_3 行 python 代码帮你轻松实现” 自动发送测试报告 “到指定邮箱...
- python计算圆的周长和面积
- Improving Training of Text-to-image Model Using Mode-seeking Function
- 文章5:多功能智能跟随行李箱控制系统设计 | 本科毕业设计 - 【控制器的学习ARDUINO+STM32】
- 软件测试人员不知道这60个工具,直接损失一个亿
- 有一行电文,已按下面规律译成密码: A →Z B→Y C→X …… a→z b→y c→x …… 即第一个字母变成第26个字母,第i个字母变成第(26-i+1)个字母,非字母字
- 动态规划作业 最长单调递增子序列