Java简单操作常用哈希算法加密

目录

一、相关概念

1、什么是哈希算法

2、什么是哈希碰撞

3、哈希算法的用途

(1)校验下载的文件

​编辑

(2)存储用户密码

二、常用的哈希算法

1、MD5

(1)对字符串进行加密

(2)对图片信息进行加密

 2、SHA-1

3、RipeMD160

4、小结

三、总结 


一、相关概念

1、什么是哈希算法

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

注:Java字符串的hashCode()就是一个哈希算法,它的输入是任意字符串,输出是固定的4字节int整数:

 

2、什么是哈希碰撞

 为什么不同的输入是大概率得到不同的输出,因为产生的哈希碰撞,

两个不同的输入得到了相同的输出。例如:

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

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

注:哈希算法,根据碰撞概率,哈希算法的输出长度越长,就越难产生碰撞,也就越安全。

 

3、哈希算法的用途

(1)校验下载的文件

        因为相同的输入永远会得到相同的输出,因此,如果输入被修改了,得到的输出就会不同。我们在网站上下载软件的时候,经常看到下载页显示的MD5哈希值:

Java简单操作常用哈希算法加密_第1张图片

 通过对比MD5的哈希值就可以进行效验确认是否为同一文件。

 

(2)存储用户密码

 在日常使用中,如果直接将用户的原始口令存放到数据库中,会产生极大的安全风险:
数据库管理员能够看到用户明文口令;
●数据库数据一旦泄漏,黑客即可获取用户明文口令。

        不存储原始密码的情况如何进行验证呢?例如,MD5。在用户输入原始口令后,系统计算用户输入的原始口令的MD5并与数据库存储的MD5对比,如果一致,说明密码正确,否则,密码错误。这样一来,数据库管理员看不到用户的原始口令。即使数据库泄漏,黑客也无法拿到用户的原始口令。

 

二、常用的哈希算法

算法 MD5 SHA-1 RipeMD160 SHA-256 SHA-512
输出长度(字节) 16 20 20 32 64

1、MD5

他的输出长度(字节):16 bytes

(1)对字符串进行加密

public static void main(String[] args) throws NoSuchAlgorithmException {
		
		//创建基于MD5算法的消息摘要对象
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		
		//更新原始数据
		md5.update("我自横刀向天笑".getBytes());
		
		//获取加密后结果
		byte[] digestBytes = md5.digest();
		System.out.println("加密后结果(字符数组):" + Arrays.toString(digestBytes));
		System.out.println("加密后结果(16进制字符串):" + HashTools.bytesToHex(digestBytes));
		System.out.println("加密结果长度:" + digestBytes.length);
		
		//原始内容相同,结果相同
	}

 输出结果:

 这里我们可以看到,处理过是使用byte字节数组存储的,这里我使用了自己定义的工具类HashTools中的bytesToHex()方法进行了转换成了16进制的字符串。

//将字节数组转换为16进制字符串
	public static String bytesToHex(byte[] bytes) {
		StringBuilder ret = new StringBuilder();
		for(byte b : bytes) {
			//将字节值转换为2位十进制字符串(不足2位补0)
			ret.append(String .format("%02x", b));
		}
		return ret.toString();
	}

(2)对图片信息进行加密

public static void main(String[] args) throws IOException, NoSuchAlgorithmException {
		
		//获取图片信息
		byte[] buff = Files.readAllBytes(Paths.get("C:\\Users\\GAN\\Desktop\\1\\谦谦.jpg"));
		
		//创建加密算法对象
		MessageDigest md5 = MessageDigest.getInstance("MD5");
		
		//原始数据更新
		md5.update(buff);
		
		//获取加密摘要
		 byte[] digestBytes = md5.digest();
		 System.out.println("加密后结果(字符数组):" + Arrays.toString(digestBytes));
		 System.out.println("加密后结果(16进制字符串):" + HashTools.bytesToHex(digestBytes));
		 System.out.println("加密结果长度:" + digestBytes.length);
	}

  输出结果:

这里我偷懒了,没用try,catch处理异常,直接抛出来。

我们可以看到无论是多大的信息,最后加密长度都是16个字节。

是哈希算法的输出固定长度摘要的特点。

 

 2、SHA-1

他的输出长度(字节):20 bytes

public static void main(String[] args) throws NoSuchAlgorithmException {
		
		//创建基于MD5算法的消息摘要对象
		MessageDigest md5 = MessageDigest.getInstance("SHA-1");
		
		//更新原始数据
		md5.update("我自横刀向天笑".getBytes());
		
		//获取加密后结果
		byte[] digestBytes = md5.digest();
		System.out.println("加密后结果(字符数组):" + Arrays.toString(digestBytes));
		System.out.println("加密后结果(16进制字符串):" + HashTools.bytesToHex(digestBytes));
		System.out.println("加密结果长度:" + digestBytes.length);
		
		//原始内容相同,结果相同
	}

   输出结果:

 

3、RipeMD160

他的输出长度(字节):20 bytes

public static void main(String[] args) throws NoSuchAlgorithmException {
		//注册BouncyCastleProvider通知类
		//将提供的消息摘要算法注册至Security
		Security.addProvider(new BouncyCastleProvider());
		
		//获取RipeMD160算法的消息摘要对象
		MessageDigest ripeMd160 = MessageDigest.getInstance("RipeMD160");
		
		//更新原始数据
		ripeMd160.update("我自横刀向天笑".getBytes());
		
		//获取消息摘要
		byte[] result = ripeMd160.digest();
		
		//消息摘要的字节长度与内容
		System.out.println("加密结果长度:" + result.length);
		System.out.println("加密结果内容:" + Arrays.toString(result));
	
	}

 输出结果:

 

 RipeMD160与上述算法不同,不是java基础库中自带的算法,所以需要导入第三方库bcprov-jdk15on-1.70.jarb,且在使用时需要进行安全注册。

4、小结

在上述的几种算法中我们可以看到,在实现加密的代码中,步骤完全相同,所以我们为了方便可以进行一部分的提取,进行代码复用,这里我写入了工具类中。

//消息摘要对象
	private static MessageDigest digest;
	
	private  HashTools() {
		
	}
	
	//MD5加密方法
	public static String digestByMD5(String source) throws NoSuchAlgorithmException {
		digest =MessageDigest.getInstance("MD5");
		return handler(source);
	}
	
	//SHA-1加密方法
	public static String digestBySHA1(String source) throws NoSuchAlgorithmException {
		digest =MessageDigest.getInstance("SHA1");
		return handler(source);
	}
	
	//SHA-256
	public static String digestBySHA256(String source) throws NoSuchAlgorithmException {
		digest =MessageDigest.getInstance("SHA-256");
		return handler(source);
	}
	
	//SHA-512
	public static String digestBySHA512(String source) throws NoSuchAlgorithmException {
		digest =MessageDigest.getInstance("SHA-512");
		return handler(source);
	}
    //处理方法
	private static String handler(String source) {
		digest.update(source.getBytes());
		byte[] bytes = digest.digest();
		String hash = bytesToHex(bytes);
		return hash;
	}

简单应用: 

public static void main(String[] args) {
		
		try {
			//MD5加密
			String md5 = HashTools.digestByMD5("wzhdxtx");
			
			//SHA-1加密
			String sha1 = HashTools.digestBySHA1("wzhdxtx");
			//SHA-256
			String sha2 = HashTools.digestBySHA256("wzhdxtx");
			//SHA-512
			String sha3 = HashTools.digestBySHA512("wzhdxtx");
			System.out.println("MD5加密:" + md5);
			System.out.println("SHA-1加密:" + sha1);
			System.out.println("SHA-256加密:" + sha2);
			System.out.println("SHA-512加密:" + sha3);
		} catch (NoSuchAlgorithmException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

 

三、总结 

        哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。

        常用的哈希算法有MD5(16),SHA-1(20)、RipeMD160(20)、SHA-256(32)、SHA-512(64)。

        加密步骤:

  • 1.创建算法的消息摘要对象
  • 2.更新原始数据
  • 3.获取摘要结果

 

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