Java加密:常见哈希算法总结

目录

一、概述

二、哈希碰撞

三、常见的哈希算法

 四、简单应用代码实现

下面先以MD5算法对密码进行加密为例:

哈希算法的用途 

扩展: 

一、概述

       哈希算法(Hash)又称摘要算法(Digest ),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。哈希算法的目的:为了验证原始数据是否被篡改。
哈希算法最重要的特点就是:

·相同的输入一定得到相同的输出;

·不同的输入大概率得到不同的输出。

二、哈希碰撞

哈希碰撞是指,两个不同的输入得到了相同的输出,比如:

"AaAaAa".hashCode(); // 0x7460e8c0
"BBAaBB".hashCode(); // 0x7460e8c0

"通话".hashCode(); // 0x11ff03
"重地".hashCode(); // 0x11ff03

       碰撞能不能避免?答案是不能。碰撞是一定会出现的,因为输出的气节长度是固定的,String的hashcode()输出是4字节整数,最多只有4294967296种输出,但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞。
       碰撞不可怕,我们担心的不是碰撞,而是碰撞的概率,因为碰撞概率的高低关系到哈希算法的安全性。一个安全的哈希算法必须满足:
       ·碰撞概率低;
       ·不能猜测输出。

三、常见的哈希算法

算法 输出长度(位) 输出长度(字节)
MD5 128 bits 16 bytes
SHA-1 160bits 20 bytes
RipeMD-160 160bits 20 bytes
SHA-256 256 bits 32 bytes
SHA-512 512 bits 64 bytes

 四、简单应用代码实现

下面先以MD5算法对密码进行加密为例:

       首先在使用MessageDigest时,我们首先根据哈希算法获取一个MessageDigest 实例;

       然后,反复调用update(byte[])输入数据;

       当输入结束后,调用digest()方法获得byte[]数组表示的摘要

       最后,把它转换为十六进制的字符串,借助String.format("%02x", bite)格式化控制。

public class demo02 {
	public static void main(String[] args) {
		try {
			String password = "123wbjxxmynhmyzgq";
		
			//根据当前算法,获取加密工具对象(摘要)
			MessageDigest digest = MessageDigest.getInstance("MD5");
			
			//更新原始数据
			digest.update(password.getBytes());
			
			//加密后的字节数组,转换字符串
			byte[] resultByteArray = digest.digest();
			StringBuilder result = new StringBuilder();
			
			for(byte bite : resultByteArray) {
				//字符串格式化控制:转换成16进制,每个数字占两个字节,不足0来补
				result.append(String.format("%02x", bite));
			}
			
			System.out.println(result);
			System.out.println(result.length());
			
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
		
	}

}

哈希算法的用途 

1.校验下载文件

  我们只需要计算本地文件的哈希值,再与官网公开的哈希值对比,如果相同,说明文件下载正确,否则,说明文件已经被篡改。因为相同的输入永远会得到相同的输出,如果输入被修改了,得到的输出就会不同。

 

Java加密:常见哈希算法总结_第1张图片

2.存储用户密码

为了防止密码泄露和抵御彩虹表的攻击,我们需要对每个口令额外添加随机数,这个方法称之为盐(salt)。

下面介绍用哈希算法SHA-1对密码进行加密:

①获取SHA-1算法的工具对象MessageDigest,通过getInstance("SHA-1")来进行创建;

②使用update()更新数据(添加数据);

③通过digest()方法获取加密信息(消息摘要);

④使用StringBuilder将加密信息格式化成16进制拼接成字符串输出。

public class demo04 {
	public static void main(String[] args) throws NoSuchAlgorithmException {
		String password = "wertyuisdf";
		String salt = UUID.randomUUID().toString().substring(0, 5);
		System.out.println(salt);
		
		//获取SHA-1算法的工具对象
		MessageDigest digest = MessageDigest.getInstance("SHA-1");
		digest.update(password.getBytes());
		digest.update(salt.getBytes());
		
		byte[] resultByteArray = digest.digest();
		
		System.out.println(Arrays.toString(resultByteArray));
		System.out.println(resultByteArray.length);
		
		StringBuilder result = new StringBuilder();
		for(byte b : resultByteArray) {
			result.append(String.format("%02x", b));
		}
		System.out.println(result);
		
		
	}

}

 输出加密内容长度、加密内容:

 

扩展: 

首先介绍bouncyCastle:提供了很多哈希算法和加密算法的第三方开源库
下面介绍哈希算法 RipeMD-160算法实现过程:

①注册BouncyCastle提供的通知类对象BouncyCastleProvider;

②获取RipeMD160算法的“消息摘要对象”(加密对象)MessageDigest.getInstance("RipeMD160");

③更新原始数据update()

④通过调用digest()方法获取消息摘要(加密)

⑤输出具体信息,此次借助BigInteger(1,result).toString(16),1表示输出类型为正整数,16表示转换成16进制,将消息摘要输出。

public class demo {
	public static void main(String[] args) {
		try {
			//注册BouncyCastle提供的通知类对象BouncyCastleProvider
			Security.addProvider(new BouncyCastleProvider());
			
			//获取RipeMD160算法的“消息摘要对象”(加密对象)
			MessageDigest md = MessageDigest.getInstance("RipeMD160");
			
			//更新原始数据
			md.update("HelloWorld".getBytes());
			
			//获取消息摘要(加密)
			byte[] result = md.digest();
			
			//消息摘要的字节长度和内容
			System.out.println(result.length); //160位 = 20字节
			System.out.println(Arrays.toString(result));
			
			//16进制内容字符串
			//1 代表类型为正整数
			String hex = new BigInteger(1,result).toString(16);
			System.out.println(hex.length()); //20字节 = 40个字符
			System.out.println(hex);
			
		} catch (NoSuchAlgorithmException e) {
			e.printStackTrace();
		}
	}

}

 输出结果:

 

 以上就是对于哈希算法总结以及简单应用实现的分享,如有不当之处还请大家多多评论指正,喜欢的话可以留下您的关注和点赞,一起学习,一起进步!



 


 

你可能感兴趣的:(java,哈希算法,开发语言)