消息摘要(Message Digest)及其算法

文章目录

      • 消息摘要(Message Digest,MD)
      • 哈希(Hash)及算法
        • Hash概念及特点
        • Hash函数分类
        • Hash碰撞(Collision)
        • Hash算法
        • Hash算法比较
        • 应用
      • MD5等算法的安全性
      • 哈希表(HashMap,Hash Table)
        • 哈希表、数组和链表

此篇是对
Java之消息摘要(MD5)的深入与补充。

消息摘要(Message Digest,MD)

摘要的意思是摘录的要点,文章的摘要是指的是该文章的内容提要。信息领域的消息摘要是对一个数据块的数字指纹。
这里对一段消息的摘要不是该消息的内容提要,而是该消息的数字指纹,是一串固定长度的字符串。消息摘要具有以下属性:

  1. 消息改变, 摘要必然不一样
  2. 不能伪造相同摘要的不同消息。
    消息摘要最著名的算法就是SHA1和MD5。建议使用SHA1。

消息摘要是数据块的指纹, 在签署合同时,签署双方按上指纹以确定合同的有效性,如果双方签署下一个合同,按的指纹是一样的。而不同的合同产生出来的消息摘要是不一样的,除非两份合同完全一致。

哈希(Hash)及算法

Hash概念及特点

Hash,直译是“哈希”,更常见的翻译是“散列”,也有翻译为“杂凑”。其定义是将任意长度的输入通过散列算法换成固定长度的输出,这个输出就是散列值。
以数学中求模算法为例: 9%2的结果是1, 19%2的结果也是1,但哈希算法远比这复杂。其输入可以是字符串、文本或是文件,其输出是固定长度的哈希值。
消息摘要(Message Digest)及其算法_第1张图片

Hash函数分类

Hash算法,也称Hash函数或散列函数。哈希算法将数据打乱混合,创建一个唯一的哈希值。
Hash函数是一种单向的加密体制,将任意长度的输入经过转换得到固定长度的输出,但这个过程不可逆,只有加密过程,没有解密过程。常见的哈希函数分类有:

  1. 加法Hash: 利用加法构造。
  2. 位运算 Hash: 利用移位或异或来混合输入元素。
  3. 乘法Hash
  4. 除法Hash
  5. 查表Hash
  6. 混合Hash:混合以上的方式,比如MD5等

Hash碰撞(Collision)

不同的输入使用Hash函数获取的Hash值如果相同,则称发生了碰撞。也就是不同的消息,产生相同的消息摘要。
对于简单的加法或是乘法函数,出现碰撞的可能性很大;对于MD5等算法,虽然概率非常小,但是在理论和现实中都是存在的,这样的算法也就是不安全的了。
好的Hash函数(f)应当满足以下3个条件:

  1. 不能从应变量得到自变量。也就是f(x)=y函数,对于任意的y, 不能找到x。
  2. 弱无碰撞性。给定x1∈A,找x2∈B,,使得f(x1)=f(x2),在计算上是不可能的
  3. 强无碰撞性,寻找x1,x2,使得f(x1)=f(x2),在计算上也是不可行的。
    碰撞的处理方法有两类: 开放寻址法(Open Addressing)和链接法(Chaining)。

Hash算法

常见的Hash算法有:MD(Message Digest,消息摘要)、SHA(Secure Hash Algorithm,安全摘要)和MAC(Message Authentication Code,消息认证码)。
MD5和SHA1应该是目前适用最为广泛的Hash算法,这两个算法是在MD4基础上产生。

  1. MD4, MD是Message Digest的简写,由MIT(麻省理工)在1990年设计,是基于32位系统实现。输出128位。

  2. MD5, 1991年MD4改进。相比MD4,速度稍慢,但更安全。
    MD5以512位分组来处理输入信息,每一分组会分为16个32bit子分组,经过算法处理后,最终输出有4个32位分组组成,将这4个32位分组级联组成 128位散列值。

  3. SHA-1,输出160位。

  4. SHA-2,包括SHA-224、SHA-256、SHA-384、SHA-512,后面是输出的位数。

  5. MAC,带密钥的Hash函数。
    MD5和SHA函数都只有一个输入参数:消息。 如果增加一个密钥(key)的参数,则会生成一个加密的消息摘要。

Hash算法比较

信息摘要越长,发生碰撞的几率就越低,破解难度就越大,但同时,耗费的性能和占用的空间就越高。
这里主要比较MD5和SHA-1的差异。
MD5摘要长度128bit,SHA-1摘要长度160bit,SHA-1比MD5多出了32bit,也就是对原文的碰撞几率降低了2^32 = 324294967296倍,但SHA-1比MD5性能略低。
摘要最终的。
在https://www.cmd5.com/ 可以查到使用不同摘要算法产生的字符串。
消息摘要(Message Digest)及其算法_第2张图片
消息摘要(Message Digest)及其算法_第3张图片

应用

消息摘要可以用来加密字串和验证内容是否被篡改,依据此特性,实际的应用包括:

  1. 数据完整性检查(Data Integrity Check)
    用作SSL/TLS/IPsec, 原始数据生成消息摘要,共享对称密钥加密,接收方逆操作

  2. 数字证书签名(Digital Certification Signature)
    将服务器的数字证书生成消息摘要,用CA的私钥加密,这个MD就变成了CA的数字签名,附在原始证书的末尾,作为CA签名的数字证书
    服务端与客户端认证时,将CA签名证书发给客户端,客户端拥有CA的公钥(手动或浏览器安装),可以解密CA的数字签名,得到消息摘要。然后客户端自身使用Hash算法运算数字证书,比较两个消息摘要是否一致,一致则认证通过。

  3. 数据校验(Checksum),验证软件没有被篡改。
    将原始文件生成MD5 Checksum,用户下载完文件,计算下载文件的MD5 Checksum,如果相同,则文件完好。
    以JDK 8的下载为例,在https://www.oracle.com/webfolder/s/digest/8u241checksum.html可以看到安装文件的Checksum。界面如下:
    消息摘要(Message Digest)及其算法_第4张图片

  4. 数据来源可靠性认证

  5. 密码加密, 密码通过Hash算法(比如MD5)加密后存入数据库,即使被截取了,也无法得到原密码。

MD5等算法的安全性

在实际应用中,MD5产生的消息摘要除了用来验证数据的完整性,也常被用来对密码加密。在很多应用中,用户的密码都会被MD5加密后存入数据库。但密码丢失时,一般就只能重置密码而无法找回。这看上去很完美。但2004年的国家密码学年会上,山东大学王小云教授的"破译md5、haval-128、md4以及ripemd-128算法"的报告,实现了MD5的破译。更神奇的还是来看 http://www.cmd5.com/ 这个网站。
在密文输入消息摘要,点“查询”之后就可以看到原文了。
消息摘要(Message Digest)及其算法_第5张图片
这看上去有悖摘要算法的原理,不是压缩计算?不是不可逆吗? 为什么可以得到原文呢?看一下该网站的介绍稍稍安心了。该网站通过反向查询的方法获取结果,存储了大量的原文和摘要的对应。但是不管怎样, MD5等都不是很安全了。

在这里插入图片描述

哈希表(HashMap,Hash Table)

在Java等语言中, HashMap是一种常用的数据结构,以键值对的方式存储和访问数据的格式,优势是查找数据较快。
哈希表,也成为散列表,是基于快速存储的角度而设计,该数据结构可以理解为一个线性表,但其中的元素不是紧密排列的。
把键映射到表中位置的函数就是映射函数。
在HashMap中的较好的散列函数是使数据元素更快的被定位,常见的方法有:

  1. 直接寻址, 去关键字或关键子的某个线性函数为散列地址。 表达式为:
    H(key)=key 或 H(key)=akey+b
    比如: 以公司员工的出生年月日为键。
  2. 数字分析法。 找出数字的规律,尽可能利用这些数据构造冲突几率较低的散列地址。
    沿用上面的示例,出生年月日有很大的可能性出现冲突。这时候可以分析数据,找到合适的键。
  3. 平方取中法。取关键字平方后的中间几位作为散列地址。
  4. 折叠法。将关键字分割成位数相同的几部分,最后一部分位数可以不同,然后取这及部分的叠加和作为散列地址。
  5. 随机数法。 选择一随机函数,取关键字的随机值作为散列地址,通常适用于关键子长度不同的场合。
  6. 除留余数法。取关键子被某个不大于散列表长m的数p除后所得的余数为散列地址。

哈希表、数组和链表

  • 数组是元素的有序序列,在内存中也是按照这个先后顺序连续存放在一起。在Java中的整型数组 int a[10]。
  • 链表是物理上非连续、非顺序的存储结构,数据元素的逻辑顺序通过链表中的指针链接次序实现。
    简单数据结构如下:
    消息摘要(Message Digest)及其算法_第6张图片
    数组寻址容易,也就是查找容易,但插入和删除难; 链表寻址困难,但插入和删除容易。如果将数组和链表组合在一起,就可以发挥两者的优势。
    消息摘要(Message Digest)及其算法_第7张图片
    如何根据数组的特征计算下标就要使用哈希算法了。哈希算法根据Key来定位其在HashMap中的位置。
    在JDK 8中,通过hashCode()的高16位异或低16位实现的:(h = k.hashCode()) ^ (h >>> 16),主要是从速度、功效、质量来考虑的。以上方法得到的int的hash值,然后再通过h & (table.length -1)来得到该对象在数据中保存的位置。
    在这里插入图片描述

你可能感兴趣的:(Web开发安全)