C#:生成哈希字符串
目录
介绍
背景
哈希助手类
考虑
对象到哈希字符串的过程
多个对象组合的哈希
我们将更频繁地使用的方法
整个对象的哈希
重要的是记住
数据值散列
哈希结果
其他测试
奖励:字符串哈希
结论
- 下载源代码 - 5.9 KB
介绍
散列是将值转换为通常较短的固定长度的键/值,其表示原始值。几天前,我们不得不使用哈希比较来通过API在两个系统之间同步数据(显然,这不是使用API进行数据同步的最有效方式,但我们没有选择在源端添加任何更改) 。
背景
我们在做什么:
- 在对象JSON反序列化之后在我们的末尾创建一个哈希字符串
- 通过唯一标识符(主键)将该哈希字符串与现有数据库行进行比较
- 如果唯一标识符(主键)找不到行,则向DB添加新行
- 如果哈希字符串不相同,则使用新值更新现有行
- 还有其他几个同步日志进程
一切都按预期工作,直到我们重构现有代码(更改了一些模型和属性的名称)。哈希字符串是从整个对象(包括所有值)生成的,而不是考虑特定的属性。我们创建哈希字符串的方式实际上是错误的。我们来看几个哈希字符串示例。
哈希助手类
这是用于管理与哈希相关的操作的实用程序类。
using System.IO;
using System.Linq;
using System.Runtime.Serialization.Formatters.Binary;
using System.Security.Cryptography;
using System.Text;public class HashHelper
{/// <summary>/// for custom class need [Serializable]/// to ignore https://stackoverflow.com/questions/33489930//// ignore-non-serialized-property-in-binaryformatter-serialization/// </summary>/// <param name="value"></param>/// <returns></returns>public byte[] Byte(object value){/*https://stackoverflow.com/questions/1446547/how-to-convert-an-object-to-a-byte-array-in-c-sharp*/using (var ms = new MemoryStream()){BinaryFormatter bf = new BinaryFormatter();bf.Serialize(ms, value == null ? "null" : value);return ms.ToArray();}}public byte[] Hash(byte[] value){/*https://support.microsoft.com/en-za/help/307020/how-to-compute-and-compare-hash-values-by-using-visual-cs*//*https://andrewlock.net/why-is-string-gethashcode-different-each-time-i-run-my-program-in-net-core*/byte[] result = MD5.Create().ComputeHash(value);return result;}public byte[] Combine(params byte[][] values){/*https://stackoverflow.com/questions/415291/best-way-to-combine-two-or-more-byte-arrays-in-c-sharp*/byte[] rv = new byte[values.Sum(a => a.Length)];int offset = 0;foreach (byte[] array in values){System.Buffer.BlockCopy(array, 0, rv, offset, array.Length);offset += array.Length;}return rv;}public string String(byte[] hash){/*https://stackoverflow.com/questions/1300890/md5-hash-with-salt-for-keeping-password-in-db-in-c-sharp*/StringBuilder sb = new StringBuilder();for (int i = 0; i < hash.Length; i++){sb.Append(hash[i].ToString("x2")); /*do not make it X2*/}var result = sb.ToString();return result;}public byte[] Hash(params object[] values){byte[][] bytes = new byte[values.Length][];for(int i=0; i < values.Length; i++){bytes[i] = Byte(values[i]);}byte[] combined = Combine(bytes);byte[] combinedHash = Hash(combined);return combinedHash;}/*https://stackoverflow.com/questions/5868438/c-sharp-generate-a-random-md5-hash*/public string HashString(string value, Encoding encoding = null){if (encoding == null){encoding = Encoding.ASCII;}byte[] bytes = encoding.GetBytes(value);byte[] hash = Hash(bytes);string result = String(hash);return result;}public string HashString(params object[] values){var hash = Hash(values); /*Add more not constant properties as needed*/var value = String(hash);return value;}
}
考虑
- 使用MD5哈希Hash(byte[] value)
- 任何null 值都被视为'null'字符串Byte(object value)
对象到哈希字符串的过程
- 创建该对象的字节 Byte(object value)
- 从对象字节Hash(byte[] value)创建哈希字节
- 散列字节String(byte[] hash)中返回的字符串
多个对象组合的哈希
- 创建每个对象的字节 Byte(object value)
- 将字节组合或求和 Combine(params byte[][] values)
- 从组合创建哈希字节或对字节求和 Hash(byte[] value)
- 散列字节String(byte[] hash)中返回的字符串
或者:
- 创建组合哈希字节 Hash(params object[] values)
- 散列字节String(byte[] hash)中返回的字符串
我们将更频繁地使用的方法
- 创建任何字符串的哈希字符串 HashString(string value, Encoding encoding = null)
- 创建任何/对象组的哈希/组合哈希字符串 HashString(params object[] values)
整个对象的哈希
数据类或模型:
[Serializable]
class PeopleModel
{public long? Id { get; set; }public string Name { get; set; }public bool? IsActive { get; set; }public DateTime? CreatedDateTime { get; set; }
}
创建模型的哈希:
/*9105d073ad276d742c56a049abd4ddef* will change if we change * 1. class name* 2. property name* 3. property data type* 4. add/remove new property etc*/
var peopleModelHashString = hashHelper.HashString(new PeopleModel()
{Id = 1,Name = "Anders Hejlsberg",IsActive = true,CreatedDateTime = new DateTime(1960, 12, 2)
});
重要的是记住
此哈希取决于对象结构和分配的值。即使我们为属性分配相同的值,生成的哈希也不会相同,但添加了一些更改,如:
- 类/模型名称更改
- 属性名称更改
- 命名空间名称更改
- 属性编号更改(添加或删除任何属性)
到模型。而在开发环境中,重构可能发生的任何时间。
数据值散列
让我们只使用值进行哈希。创建一个接口IHash。
public interface IHash
{string HashString();
}
使用IHash到模型并在方法HashString()内部使用哈希助手。
class People : IHash
{public long? Id { get; set; } /*unique identifier, avoid it to use in hash calculation*/public string Name { get; set; }public bool? IsActive { get; set; }public DateTime? CreatedDateTime { get; set; }public string HashString(){var value = new HashHelper().HashString(Name, IsActive, CreatedDateTime); /*Add more not constant properties as needed*/return value;}
}
这样,模型结构不参与哈希生成过程中,只有特定的属性值(Name,IsActive,CreatedDateTime)正被考虑。
Hash将保持不变,直到没有为这些属性设置任何新值。模型的任何结构更改(名称更改,属性添加/删除等)都不会影响哈希字符串。
哈希结果
/*constant: 3953fbec5b81ccca72c98655c0c4b069*/
people = new People()
{Id = 1,Name = "Dennis Ritchie",IsActive = false,CreatedDateTime = new DateTime(1941, 9, 9)
};
hashString = people.HashString();
其他测试
使用null 对象值正常工作:
string hashString;
/*constant: 47ccecfc14f9ed9eff5de591b8614077*/
var people = new People();
hashString = people.HashString();
我们将无法创建整个People类,因为它不使用[Serializable]:
var hashHelper = new HashHelper();
/*throws error as [Serializable] not been used*/
//var peopleHashString = hashHelper.HashString(people);
奖励:字符串哈希
创建密码/字符串哈希是很常见的。所以我们拥有它。
/*constant: e6fb7af54c39f39507c28a86ad98a1fd*/
string name = "Dipon Roy";
string value = new HashHelper().HashString(name);
结论
- 如果我们只需要比较考虑值或特定值,那么使用数据值哈希是最佳选择。
- 但是如果我们需要完全比较对象结构和值,请选择整个对象的哈希。
原文地址:https://www.codeproject.com/Tips/5130239/Csharp-Generating-Hash-String
C#:生成哈希字符串相关推荐
- Python 生成文件或字符串的 sha256
例子当然要简洁,废话当然要少说,这块主要以 sha256 为例来进行说明,当然你可以选择 sha512 .md5 等其他算法! 文件的 sha256 这里唯一要注意的一点:文件一定要以二进制的形式打开 ...
- java 字符串转哈希_从哈希字符串转换字节,java与python
我在将纯java Curve25519函数转换为Python等效函数时遇到问题,具体问题与将哈希字符串转换为等效字节的摘要函数有关,java实现: 数据示例: sP="这是用于测试的密码短语 ...
- ruby 生成哈希值_Ruby哈希值和可变的默认值
ruby 生成哈希值 Ruby's Hash object is an associative data structure used to store key-value pairs. Many l ...
- 生成24位字符串ID__IdGenerator.java
此工具类用于生成24位字符串ID,唯一不重复. 直接通过 IdGenerator.get() 获取. 源码如下:(点击下载源码 - IdGenerator.java ) 1 import java.n ...
- python使用fpdf将生成的长字符串手动换行写入pdf
python使用fpdf将生成的长字符串手动换行写入pdf 目录 python使用fpdf将生成的长字符串手动换行写入pdf #lassocv生成特征系数dataframe
- python使用textwrap包在已经生成的长字符串中嵌入回车符实战
python使用textwrap包在已经生成的长字符串中嵌入回车符实战 目录 python使用textwrap包在已经生成的长字符串中嵌入回车符实战 # textwrap包在长字符串中嵌入回车符 #实 ...
- Android程序获得APP哈希值,Android – SMS Retriever API – 计算应用程序的哈希字符串问题...
我是Android的新手,我正在尝试实现SMS Retriever API,以便在我的应用中使用OTP. 不幸的是,我陷入了"计算你的应用程序的哈希字符串"的部分 我在这里引用了指 ...
- boost :: hash_combine从类的不同成员生成哈希值
boost :: hash_combine从类的不同成员生成哈希值 实现功能 C++实现代码 实现功能 Boost的container_hash模块,boost :: hash_combine从类的不 ...
- ruby 生成哈希值_哈希== Ruby中的运算符
ruby 生成哈希值 In the last article, we have seen how we can compare two hash objects with the help of &l ...
最新文章
- 神经正切核,深度学习理论研究的最新热点?
- NetDevOps — PyEZ
- java mysql 分布式锁_Java分布式锁之数据库方式实现
- Spring可扩展Schema标签
- Finding Gems
- Java中Thread类的方法简介
- 49 SD配置-定价配置-定义条件类型
- Leetcode 1219.黄金矿工
- 使用Windows迁移工具迁移2003至2012R2 二、IP迁移
- java坦克大战爆炸效果_Java坦克大战第一个坦克不爆炸问题
- 组网[ZeroTier]+自建Moon服务
- 各种说明方法的例句_举例子,列数字,作比较,打比方,这几个说明方法的例句...
- xss.haozi靶场通关
- 虚拟机挂载优盘和识别优盘
- 微信小程序与公众号区别PHP,微信小程序和微信公众号的区别是什么?
- 计量经济学笔记5-Eviews操作-异方差的检验与消除(White检验与加权最小二乘)
- CCC认证费用是多少?
- Stopwatch常用方法,不积硅步无以至千里
- eCharts.js使用心得
- 高保真Axure原型设计实战 - 自适应后台框架
热门文章
- hadoopsdk使用_使用 IDEA 搭建 Hadoop3.1.1 项目
- 如何在设计项目中使用冷调酷色
- 壁纸图片|2020年12月游戏图片大全
- 设计灵感合集|拟人化创意合成小动物,治愈可爱风插画作品
- 就知道你会没灵感,感恩节psd分层海报模板来咯!
- UI设计素材模板|设计良好的教育网站:3个快捷技巧
- UI素材实用模板|2.5D等距风格插画专辑
- lambert(兰伯特)投影 应用工具_全息投影技术,在哪些场地可以用到
- python合法的变量名有哪些_Python判断变量名是否合法的方法示例
- asp.net 添加权限