什么是hash算法,hash算法的三个条件

首页 > 经验 > 作者:YD1662022-11-04 12:28:11

上一篇文章里面,我们介绍了随机数以及随机数中的应用,可以看到密码学中到处都有随机数的身影,这种作为大部分密码学算法的基本组成被称之为 “加密基元“。今天我们一起来看一下另外一个加密基元 - 密码学Hash算法

什么是密码学Hash算法

密码学Hash算法是一个非常重要,而且常见的算法,是计算机密码学中的核心组成部分。密码学Hash算法是指将任何长度的二进制值映射成较短的固定长度二进制值的算法,这个较短的固定长度二进制值就是Hash值。先说一下:这个表述其实不是特别严谨,“任意长度”其实应该是 “算法允许长度范围内的任意长度”,因为有些密码学Hash算法是有输入长度限制的。既然很长的输入可以变成很短的输出,这就像我们写文章之后,需要写一个摘要一样,所以Hash值很多时候也叫做 “消息摘要”, Java中计算密码学Hash值的基类更是直接叫 MessageDigest.

下面代码能够更直观一点,我们来看一些密码学Hash的例子:

public static void main(String[] args) throws NoSuchAlgorithmException { System.out.println(MD5("abcd") " <- abcd"); System.out.println(md5("abcd") " <- abcd"); System.out.println(md5("明月几时有,把酒问青天,不知天上宫阙,今夕是何年") " <- 明月几时有,把酒问青天,不知天上宫阙,今夕是何年"); System.out.println(md5("1") " <- 1 "); } ​ public static String md5(String content) throws NoSuchAlgorithmException { MessageDigest instance = MessageDigest.getInstance("MD5"); instance.update(content.getBytes()); return HexUtils.toHexString(instance.digest()); }

输出结果为:

e2fc714c4727ee9395f324cd2e7f331f <- abcd e2fc714c4727ee9395f324cd2e7f331f <- abcd 06d9a9f655c1ac1f0391e7dacfac6cbb <- 明月几时有,把酒问青天,不知天上宫阙,今夕是何年 c4ca4238a0b923820dcc509a6f75849b <- 1

密码学Hash算法的特性

密码学Hash算法有好几个特性:

密码学Hash算法的分类

密码学Hash算法大致可以分为两个类别:普通的密码学Hash算法以及安全的密码学Hash算法。 前面列的几个密码学Hash算法的特性是所有Hash算法都具备的,不管是普通的还是安全的。而安全的密码学Hash算法则多了如下几个特性:

对于攻击者来说,Hash算法的破解难度为 强抗碰撞 < 弱抗碰撞 < 单向性。也就是说 首先破解的是 强抗碰撞,随便找,只要能找到两个不同的输入有相同的输出就算 破解了。这里的破解 也分为理论破解和实际破解, 一个Hash算法理论上产生了破解,不代表在实际使用场景中不能使用该算法,因为现实世界发生碰撞的可能性还是很大的。再退一步说,即使发生了实际破解,也不代表不能用,比如MD5 早就理论跟实际都破解了,但你如果只是用于内部系统进行消息完整性地校验,那应该可以大胆地用。

接下来我们来看几种常见的Hash算法:

MD5

MD5 - Message Digest #5 是MIT教授1992年公开一种Hash算法,它接收任意长度的输入,输出一个128位的Hash值。这个算法其实挺佛性的:不管你来多大的输入,1位也行,100GB也行,我最终的输出有且仅有128位。比如前面数字 1 的MD5 hash值是c4ca4238a0b923820dcc509a6f75849b <- 1 , 由32个十六进制的字符,所以总输出位数为 32 x 4 =128位。2004年,这个算法被中科院王小云院士证明了可以产生碰撞。所以在一些安全要求比较高的场合下,慢慢地不再用MD5算法了。但是MD5还是出现在很多实现当中,因为它虽然打破了强碰撞性,但是单一性还是有的,而且它的输出是常见的Hash算法里面最短的,只有128位。

SHA

安全的密码学算法SHA - Secured Hash Algorithm, 是一组密码学Hash算法的总称。由美国国家标准与技术研究院(NIST)指定的算法。主要有3类算法: SHA-1, SHA2, SHA-3.

什么是hash算法,hash算法的三个条件(1)

Java 中密码学Hash算法的使用

Java的SDK中已经内置了MD5, SHA1, SHA2的Hash算法,我们可以很方便地使用这些算法. 而SHA-3不包含在JDK里面,需要在maven里面引入Bouncy Castle的包

<dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.56</version> </dependency>

public class HashUtil { ​ public static void main(String[] args) throws NoSuchAlgorithmException { System.out.println("abcd -> " md5("abcd")); System.out.println("abcd -> " sha1("abcd")); System.out.println("abcd -> " sha2("abcd")); System.out.println("abcd -> " sha3("abcd")); } ​ public static String md5(String content) throws NoSuchAlgorithmException { MessageDigest instance = MessageDigest.getInstance("MD5"); instance.update(content.getBytes()); return HexUtils.toHexString(instance.digest()); } ​ public static String sha1(String content) throws NoSuchAlgorithmException { MessageDigest instance = MessageDigest.getInstance("SHA-1"); instance.update(content.getBytes()); return HexUtils.toHexString(instance.digest()); } public static String sha2(String content) throws NoSuchAlgorithmException { MessageDigest instance = MessageDigest.getInstance("SHA-256"); instance.update(content.getBytes()); return HexUtils.toHexString(instance.digest()); } ​ public static String sha3(String content) throws NoSuchAlgorithmException { Digest digest = new SHA3Digest(256); digest.update(content.getBytes(),0, content.length()); byte[] hashArray = new byte[digest.getDigestSize()]; digest.doFinal(hashArray, 0); return HexUtils.toHexString(hashArray); } }

可以看到输出为:

abcd -> e2fc714c4727ee9395f324cd2e7f331f abcd -> 81fe8bfe87576c3ecb22426f8e57847382917acf abcd -> 88d4266fd4e6338d13b845fcf289579d209c897823b9217da3e161936f031589 abcd -> 6f6f129471590d2c91804c812b5750cd44cbdfb7238541c451e1ea2bc0193177

密码学Hash算法的使用场景

数据一致性

密码学Hash算法有 根据相同的输入不管运行多少次都会得到相同的输出这个特性,那么我们就可以用来作为数据一致性的校验:

身份验证

前面提到密码学Hash算法必须具备有单向性,也就是不可逆,不能从Hash值逆向推算出原始值,基于这种特性,我们可以用来进行用户身份验证。用户登录都需要进行用户名密码的校验,如果我们将用户密码存在数据库里面,一旦数据库泄露,那就所有人的密码都泄露了,这样的事情前几年发生了不少!那么如果我们将用户的原始密码进行Hash运算,并只是把Hash值保存在数据库里面,当用户登录时,我们计算用户输入密码的Hash值,并与数据库的Hash值进行比较,如果相同则验证通过,不同则失败。而用户的明文密码不进行保存,这样一来,万一数据库泄露了,也不会一下子泄露了全部的用户密码。当然,这样也避免不了彩虹表以及字典攻击,不过我们可以通过对Hash算法加盐进行处理。具体的操作后面再详细介绍。

文件秒传

用没有试过向云盘上传一部1-2G的电影,结果几秒就上传成功? 以我们目前的网络基础设施,应该到不了这样的速度的。那这是怎么做的呢? 其中的一种实现方式就是Hash值的计算,在上传之前,客户端先计算出要上传文件的Hash值,然后将这个值发送回后台,后台检查是否已经存在该Hash值,如果已经存在,则告诉客户端说存在相同的文件,无需再上传,并且把对应的文件ID发给客户端就行,这样客户端就实现了秒传,同时也可以在服务器看到这个文件!

栏目热文

文档排行

本站推荐

Copyright © 2018 - 2021 www.yd166.com., All Rights Reserved.