哈希算法分类以及实现步骤

本文介绍了Java中常用的哈希算法,如MD5、SHA-1等,以及它们的使用方法。通过`MessageDigest`接口进行加密操作,展示了MD5对文本和图片的加密过程。此外,还讨论了Hmac算法和如何恢复秘钥,强调了哈希算法的单向性和固定长度特性。
摘要由CSDN通过智能技术生成

一、哈希算法的分类

常用的哈希算法有

  1. MD5  输出长度为16字节
  2. SHA-1  输出长度为20字节
  3. SHA-256   输出长度为32字节
  4. SHA-512   输出长度为64字节
  5. RipeMD-160   输出长度为10字节

无论哪种算法,对数据进行加密的过程基本一致,只有算法名称加密后结果长度的区别,所以为了实现代码复用节约资源,将数据加密等步

目录

一、哈希算法的分类

二、哈希算法的使用

1、MD5加密过程:

2、利用MD5算法对图片进行加密

 3、Hmac算法

 4、按照字节数组恢复秘钥

5、按照字符串恢复秘钥

6、ReipeMD-160


骤进行封装,处理成一个公用的工具类。

注:所有的算法都是单向加密方式,只存在加密,不存在解密的方式;并且每一个算法加密后得到的加密结果的长度是固定的,无论运行多少次结果的长度都不会改变。

public class HashTools {
	private static MessageDigest digest;

	public HashTools() {
		super();
	}
	
	public static String HashCodeMD5(String ceontent) throws NoSuchAlgorithmException {
		digest = MessageDigest.getInstance("md5");
		String res = Handler(ceontent);
		return res;
	}
	
	public static String HashCodeSHA1(String content) throws NoSuchAlgorithmException {
		digest = MessageDigest.getInstance("SHA-1");
		String res = Handler(content);
		return res;
	}
	
	public static String Handler(String content) {
		digest.update(content.getBytes());
		String Coderet = ArrByteToHex(digest.digest());
		return Coderet;
	}
	
	//字节数组转为16进制
	public static String ArrByteToHex(byte[] buf) {
		StringBuilder res = new StringBuilder();
		
		for(byte b : buf) {
			res.append(String.format("%02x", b));
		}
		
		return res.toString();
	}

}

二、哈希算法的使用

Java为提供了统一的接口进行对哈希算法的调用。MessageDigest是一个抽象类,在具体代码实现中,直接用MessageDigest.getInstance("MD5");参数为算法名称。

1、MD5加密过程:

(1)、创建基于MD5的消息摘要对象

MessageDigest md5 = MessageDigest.getInstance("MD5");

(2)、更新原始数据内容

参数为密码等原始数据,注意是字节

md5.update("天动万象".getBytes());

(3)、进行加密并获取加密后的结果

byte[] buf = md5.digest();
System.out.println("加密后:" + Arrays.toString(buf));
String hexres = HashTransToHex.ArrByteToHex(buf);
System.out.println("十六进制加密后" + hexres);

该方法返回值类型为字节数组,通过工具类可以得到十六进制的字符串结果。

(4)、运行结果

2、利用MD5算法对图片进行加密

(1)、创建基于MD5的消息摘要对象并拿到图片原始字节数据内容

MessageDigest imagemd5 = MessageDigest.getInstance("md5");
byte[] buff = Files.readAllBytes(Paths.get("D:\\Temp\\Test\\Cat.jpg"));

(2)、更新原始数据内容并进行加密

imagemd5.update(buff);//原始数据
byte[] imagebufres = imagemd5.digest();//获取加密摘要(进行加密)

(3)、加密结果输出

System.out.println("加密后:" + Arrays.toString(imagebufres));
String hexres = HashTools.ArrByteToHex(imagebufres);
System.out.println("十六进制加密后" + hexres);
System.out.println("加密后的字节数组长度为:" + imagebufres.length);

(4)、运行结果

 3、Hmac算法

该算法的加密结果长度固定为64字节,且每次运行生成的秘钥均不相同

由于MD5加密算法的结果比较稳定且长度一定,所以会有彩虹表等数据表能够进行密码的反推,会导致数据安全问题,在上述MD5算法中采取加随机盐值的方式。

String password = "FJQFY";
MessageDigest md5 = MessageDigest.getInstance("md5");
//加随机盐值
String salt = UUID.randomUUID().toString().substring(0, 3);
md5.update(salt.getBytes());
md5.update(password.getBytes());
String res = HashTools.ArrByteToHex(md5.digest());
System.out.println("加盐值后:" + res);

Hmac算法是一种基于秘钥的认证算法,其关键词是秘钥。具体使用步骤:

(1)、使用秘钥生成器(KeyGenerator)生成秘钥

KeyGenerator key = KeyGenerator.getInstance("HmacMD5");
SecretKey scekey = key.generateKey();

注:generateKey()方法的返回值类型是SecretKey 。

(2)、使用秘钥进行加密

获取要加密的对象,参数为算法名称

Mac mac = Mac.getInstance("HmacMD5");

初始化秘钥

mac.init(scekey);

更新原始加密内容(参数为字节类型),并进行加密操作:doFinal( )方法(返回值类型为字节数组)

mac.update(pwd.getBytes());
byte[] buf = mac.doFinal();

//使用工具类进行输出
System.out.println("使用秘钥加密后:" + Arrays.toString(buf));
System.out.println("使用秘钥加密后(十六进制):" + HashTools.ArrByteToHex(buf));
System.out.println("使用秘钥加密字节长度:" + buf.length);
System.out.println("使用秘钥加密后十六进制字符长度:" + HashTools.ArrByteToHex(buf).length());

运行结果:

 4、按照字节数组恢复秘钥

(1)、定义原始密码和秘钥(字节数组的形式)

//原始密码
String pwd = "FJQFY";
//原始秘钥(字节数组)
byte[] keybyte = {  };

(2)、恢复秘钥

参数为字节数组和算法名称

//恢复秘钥
SecretKey key = new SecretKeySpec(keybyte, "HmacMD5");

(3)、创建加密算法对象

update()方法中的参数为原始密码(字节类型)

//创建加密算法对象
Mac m = Mac.getInstance("HmacMD5");
m.init(key); //初始化
m.update(pwd.getBytes());//更新数据内容
String res = HashTools.ArrByteToHex(m.doFinal());//使用工具类进行数据处理

5、按照字符串恢复秘钥

和按照字节恢复相比,流程基本一致,只需要初始化一个长度为64的字节数组,在通过循环将字符串的没两位转换成十进制数据放入字节数组中即可;eg;

String keystr = "  XXXXXXXXXX";
byte[] buff = new byte[64];
for(int i = 0,k = 0;i<keystr.length();i = i+2,k++) {
	String s = keystr.substring(i,i+2);
	buff[k] = (byte)Integer.parseInt(s, 16);
}

6、ReipeMD-160

其具体使用步骤和上述算法一致,只是在使用前需要进行如下操作:

Security.addProvider(new BouncyCastleProvider());

此代码目的主要是用来注册BouncyCastleProvider通知类,将提供的消息摘要算法注册至Security

BouncyCastleProvider是一个通知类。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值