前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >浅谈散列运算

浅谈散列运算

作者头像
小蜜蜂
发布2019-07-24 17:10:20
发布2019-07-24 17:10:20
1.1K00
代码可运行
举报
文章被收录于专栏:明丰随笔明丰随笔
运行总次数:0
代码可运行

散列运算是什么?

提到散列运算,很多人可能首先想到的就是MD5:

Message-Digest Algorithm 5

消息摘要算法第5版

一般情况我们系统的数据库中的用户密码都是采用MD5进行加密的。

实际上,严格来说,MD5并不能称为加密,它只是一种散列运算(Hash)。

对消息进行散列运算,可以获得消息的摘要(Digest,也叫哈希值,或者指纹)。

“指纹”一词形象地描述了散列运算的结果。在现实生活中,两个人可能长得很像,但是他们的指纹不同,根据指纹就能对这两个人进行区分。

在计算机中,对数据进行散列运算,就得到了这个数据的“指纹”。只要数据不同,它的指纹就不会相同。

如果不同数据拥有相同的指纹,就叫做“碰撞”,目前MD5发生碰撞的概率极低。

散列运算具有4个特点:

1. 散列运算是不可逆的,可以将散列运算理解为单向的加密:根据原消息经过散列运算可以得到摘要(密文);但是根据摘要,无法推导出原消息。

2. 任何两个不相同的文件,哪怕只有一个字节的细微差别,得到的摘要都是完全不同的。可以用来判断文件是否相等。

3. 不论原始消息的大小如何,运算得出的摘要信息固定长度的。摘要的长度根据散列算法的不同而不同,如64位或128位等。

4. 散列运算可以接受字节数组,因此像MD5这样的算法,可以对任何数据进行散列运算并获取摘要,而不仅仅限于字符串形式的用户密码。

可以这样去理解散列算法和MD5的关系:

散列算法是一个种类,而MD5是这个种类中具体的一个实例。

除了MD5以外,还有很多种其他的散列算法,比如MD4、SHA1(Secure Hash Algorithm,安全哈希算法)等。

利用散列运算判断消息是否被篡改:

1.发送方对消息进行散列运算,得到消息摘要(原始摘要),发送消息和摘要,并说明获得摘要所使用的散列算法,如MD5。

2.接收方获得消息和原始摘要,使用相同的散列算法对收到的消息进行散列运算,重新获得一个摘要(本地摘要)。

3.对比原始摘要和本地摘要,如果两个相同,则认为消息没有被篡改;否则认为消息被篡改过了。

上面的验证机制存在一个假设,那就是原始摘要没有被篡改。如果第三方在截获并篡改了消息之后,重新计算摘要,然后将原始摘要替换掉,那么这个机制就失效了。

解决的办法是采用“密钥散列算法(Keyed Hashing Algorithms)”,具体流程如下:

1. 假设发送方要发送消息"Hello world!"。在发送之前,并不对原始消息进行散列运算,而是对消息"[MyKey]Hello world!"进行散列运算,并得到摘要,其中"[MyKey]"相当于一个密钥(此处是关键,在上一种方式中,直接对消息本身,即"Hello world!"进行了散列运算)。

2. 将消息"Hello world!"和摘要发送给接收者。

3. 假设第三方截获了消息"Hello world!"和摘要,并将消息改为了"Hi world!",但它并不知道密钥"[MyKey]",因此,它仍对消息"Hi world!"进行散列运算,得到摘要后一起发送给接收方。

4. 接收方知道密钥机制,它在收到篡改过的消息"Hi world!"和摘要后,为消息加上密钥"[MyKey]",此时消息为"[MyKey]Hi world!",然后对消息进行散列运算,重新获得一个摘要。对比"Hi world!"和"[MyKey]Hi world!"两个摘要,发现摘要不一样,就会发现消息已经被篡改过了。

在整个过程中,发送方和接收方必须保证密钥不被泄露。

从上面的例子可以看出,散列算法保证了消息的完整性,但不具备保密性,因为第三方可以直接看到消息的内容。

.Net中对散列运算支持

在.NET框架中,散列算法位于System.Security.Cryptography命名空间下,该命名空间位于mscorlib.dll程序集,由一个抽象基类HashAlgorithm和一系列子类构成,下图显示了这种关系。

散列运算的类型之间共有三级的层级关系,以SHA1为例:第一级为抽象类HashAlgorithm;第二级为抽象类SHA1,第三级为普通类SHA1Managed和密封类SHA1CryptoServiceProvider。

SHA1Managed和SHA1CryptoServiceProvider的作用相同,区别是Managed后缀的类是由托管代码写的,CryptoServiceProvider后缀的类调用的是Windows Crypto API,相当于一个包装类。

最下面的三个类SHA256、SHA384、SHA512是SHA家族的变体,它们也有对应的实现类,例如SHA256Managed和SHA256CryptoServiceProvider,简单起见,图中并未列出。

代码快速入门:

代码语言:javascript
代码运行次数:0
复制
string plainText = "Hello, world!";
// 初始化对象
// 也可以:SHA1Managed alg = new SHA1Managed();
HashAlgorithm alg = HashAlgorithm.Create(HashAlgorithmType.SHA1);
// 将字符串转化为字节数组
byte[] plainData = Encoding.UTF8.GetBytes(plainText);
// 获得摘要
byte[] hashData = alg.ComputeHash(plainData);
// 输出结果
foreach (byte b in hashData)
{
  Console.Write("{0:X2}", b);
}

public class HashAlgorithmType
{
  public const string SHA1 = "SHA1";
  public const string SHA256 = "SHA256";
  public const string SHA384 = "SHA384";
  public const string SHA512 = "SHA512";
  public const string MD5 = "MD5";
}

上面代码有两点需要注意:

1. 创建算法对象时,接受的参数类型是字符串类型,字符串的取值为:MD5、SHA、SHA1、SHA256(或SHA-256)、SHA384(或SHA-384)、SHA512(或SHA-512),也可以是类型名称,例如System.Security.Cryptography.SHA1。

2. ComputeHash()方法不仅可以接受字节数组,还可以接受流,因此可以方便地对多种数据源进行散列运算。

创建算法对象的函数签名:

代码语言:javascript
代码运行次数:0
复制
public static HashAlgorithm Create(string hashName);

ComputeHash()方法的重载:

代码语言:javascript
代码运行次数:0
复制
public byte[] ComputeHash(byte[] buffer);
public byte[] ComputeHash(Stream inputStream);

.NET还提供了一些类型用作密钥散列运算,例如MACTripleDES、HMACSHA1、HMACMD5,它们与HashAlgorithm的关系如下图所示:

密钥散列运算类型的使用和普通的散列运算类似,不过多传了一个密钥作为参数而已。

下面是示例代码:

代码语言:javascript
代码运行次数:0
复制
string key = "secret key";
byte[] keyData = Encoding.UTF8.GetBytes(key);
KeyedHashAlgorithm alg = new HMACSHA1(keyData);
//KeyedHashAlgorithm alg = KeyedHashAlgorithm.Create(KeyedHashAlgorithmType.HMACSHA1);
//alg.Key = keyData;

string plainText = "Hello, world!";
// 将字符串转化为字节数组
byte[] plainData = Encoding.UTF8.GetBytes(plainText);
// 获得摘要
byte[] hashData = alg.ComputeHash(plainData);
// 输出结果
foreach (byte b in hashData)
{
  Console.Write("{0:X2}", b);
}

public class KeyedHashAlgorithmType
{
  public const string MACTripleDES = "MACTripleDES";
  public const string HMACSHA1 = "HMACSHA1";
  public const string HMACMD5 = "HMACMD5";
}

文本回顾:

散列运算是什么

散列运算具有4个特点

散列算法保证了消息的完整性

散列算法与密钥散列算法

.Net中对散列运算支持

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-07-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 明丰随笔 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档