目录
一、哈希算法
哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法的特点:
(1)相同的输入一定得到相同的输出;
(2)不同的输入大概率得到不同的输出。
哈希算法的目的:为了验证原始数据是否被篡改。
哈希碰撞:两个不同的输入得到了相同的输出。
"通话".hashCode(); // 0x11ff03 "重地".hashCode(); // 0x11ff03
哈希碰撞是不能避免的,因为输出的字节长度是固定的,String的hashCode()输出是4字节整数,最多只有4294967296种输出,但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞。因此,一个安全的哈希算法必须满足:
(1)碰撞概率低;
(2)不能轻而易举地猜测输出。
二、常用哈希算法
在编写算法代码之前,我们首先创建一个HashTools工具类,以减少代码冗余。
//Hash算法(消息摘要算法)工具类
public class HashTools {
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("SHA-1");
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);
}
//通过消息再要对象,处理加密内容
public static String handler(String souce) {
digest.update(souce.getBytes()); //调用update()输入数据
byte[] bytes=digest.digest();
String ret=bytesToHex(bytes);
return ret;
}
//将字节数组转换为十六进制字符串
public static String bytesToHex(byte[] bytes) {
StringBuilder sb=new StringBuilder();
for(byte b:bytes) {
sb.append(String.format("%02x", b)); //将字节值转换为2为十六进制字符串
}
return sb.toString();
}
}
使用MessageDigest时,首先根据哈希算法获取一个MessageDigest实例,然后,反复调用update()输入数据。当输入结束后,调用digest()方法获得byte[]数组表示的摘要,最后,把它转换为十六进制的字符串。
1、MD5
//MD5加密
public class hashMD5 {
public static void main(String[] args) throws NoSuchAlgorithmException {
String md5 = HashTools.digestByMD5("是大眼同学呦!");
System.out.println(md5);
}
}
2、SHA-1
//SHA-1加密
public class hashSHA1 {
public static void main(String[] args) throws NoSuchAlgorithmException {
String sha1 = HashTools.digestBySHA1("是大眼同学呦!");
System.out.println(sha1);
}
}
3、SHA-256
//SHA-256加密
public class hashSHA1 {
public static void main(String[] args) throws NoSuchAlgorithmException {
String sha256 = HashTools.digestBySHA256("是大眼同学呦!");
System.out.println(sha256);
}
}
4、SHA-512
//SHA-512加密
public class hashSHA1 {
public static void main(String[] args) throws NoSuchAlgorithmException {
String sha512 = HashTools.digestBySHA512("是大眼同学呦!");
System.out.println(sha512);
}
}
5、RipeMD-160
敲RipeMD-160算法的代码之前,我们必须把BouncyCastle提供的bcprov-jdk15on-1.70.jar导入至当前项目。
下载链接:https://download.csdn.net/download/qq_36462452/87518000?utm_source=bbsseo
//RipeMD160加密
public class hashRipeMD160 {
public static void main(String[] args) throws NoSuchAlgorithmException {
//注册BouncyCastleProviderCastleProvider通知类
//将注册的消息摘要算法注册至Security
Security.addProvider(new BouncyCastleProvider());
MessageDigest ripeMD160 = MessageDigest.getInstance("RipeMD160");
ripeMD160.update("是大眼同学呦!".getBytes());
byte[] bytes = ripeMD160.digest();
System.out.println("加密后(16进制字符串):" + HashTools.bytesToHex(bytes));
}
}
三、哈希算法的用途
1、校验下载文件
因为相同的输入永远会得到相同的输出,因此,如果输入被修改了,得到的输出就会不同。我们在网站上下载软件的时候,经常看到下载页显示的MD5哈希值:
然后我们只需要自己计算一下本地文件的哈希值,再与官网公开的哈希值对比,如果相同,说明文件下载正确,否则,说明文件已被篡改。
2、存储用户密码
在数据库存储用户密码的哈希,例如,MD5。在用户输入原始口令后,系统计算用户输入的原始口令的MD5并与数据库存储的MD5对比,如果一致,说明口令正确,否则,口令错误。