目录
二、常用的哈希算法:
简介:
哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法最重要的特点就是:
●相同的输入一定得到相同的输出;
●不同的输入大概率得到不同的输出。
所以,哈希算法的目的:为了验证原始数据是否被篡改。
*有一特殊情况——哈希碰撞:两个不同的输入得到了相同的输出。
例如:
"AaAaAa".hashCode(); // 0x7460e8c0 | "通话".hashCode(); // 0x11ff03 |
"BBAaBB".hashCode(); // 0x7460e8c0 | "重地".hashCode(); // 0x11ff03 |
碰撞的原因是因为:输出的字节长度是固定的,String的hashCode()输出是4字节整数,最多只有4294967296种输出,但输入的数据长度是不固定的,有无数种输入。所以,哈希算法是把一个无限的输入集合映射到一个有限的输出集合,必然会产生碰撞。产生碰撞的后果会使安全性降低。比如信息泄露等问题。
哈希碰撞解决方案:
首先简单理解来说,当你的输出值越多越长,碰撞的几率就会越小,从而安全性就会增强。
常用的哈希算法
算法 | 输出长度(位) | 输出长度(字节) |
MD5 | 128 bits | 16 bytes |
SHA-1 | 160bits | 20bytes |
RipeMD-160 | 160bits | 20bytes |
SHA-256 | 256bits | 32bytes |
SHA-512 | 512bits | 64bytes |
【用MD5算法为例进行对于原始数据的加密】
package bianma;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class md {
public static void main(String[] args) throws NoSuchAlgorithmException{
//基于MD5算法的消息摘要对象
MessageDigest md = MessageDigest.getInstance("MD5");
//更新原始数据
md.update("Hello".getBytes());
//获取加密后的结果
byte[] results = md.digest();
System.out.println("加密后的结果:"+Arrays.toString(results));
System.out.println("加密结果长度:"+results.length);
}
}
*这里可以编写一个Hash算法(消息摘要算法)工具类,方便对于信息摘要
//Hash算法(消息摘要算法)工具类
public class HashTools {
private HashTools() {}
//将字节数组转换为16进制字符串
public static string bytesToHex ( byte[] bytes){
StringBuilder ret = new StringBuilder();
for(byte b: bytes) {
//将字节值转换为2位十六进制字符串
ret.append (String.format("%02x",b));
}
return ret.toString();
}
}
*增加MD5,SHA-1的信息摘要计算
package bianma;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class HashTools {
private static MessageDigest digest;
private HashTools(){}
public static String digestByMD5(String source) throws NoSuchAlgorithmException{
digest = MessageDigest.getInstance("MD5");
return handler(source);
}
public static String digestBySHA1(String source) throws NoSuchAlgorithmException{
digest = MessageDigest.getInstance("SHA-1");
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 String bytesToHex(byte[] bytes) {
StringBuilder ret = new StringBuilder();
for(byte b : bytes) {
ret.append(String.format("%02x", b));
}
return ret.toString();
}
}
【例一:按照MD5算法对于图片进行“加密”】
//按照MD5算法对图片进行"加密"
public class Demo03 {
public static void main(String[] args) throws IOException,NoSuchAlgorithmException {
//图片的原始字节内容
byte[] imageBuf = Files.readAllBytes(Paths.get("d:\\test\\小时.jpg"));
//创建基于MD5算法的消息摘要对象
MessageDigest md5 = MessageDigest.getInstance("MD5");
//原始字节内容(图片)
md5.update( imageBuf);
//获取加密摘要
byte[] digestBytes = md5.digest();
System.out.println("加密后的结果(字节数组):"+Arrays.toString(digestBytes));
System.out.println("加密后的结果(16进制字符串):"+HashTools.bytesToHex(digestBytes));
System.out.println("加密结果长度:"+digestBytes.length);//MD5算法的固定输出长度为16个字节
[例二:通过随即加盐,彩虹表攻击问题]
package bianma;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
public class base3 {
public static void main(String[] args) throws NoSuchAlgorithmException {
//原始密码
String password = "shixiaotian6";
//产生随机盐值
String salt = UUID.randomUUID().toString().substring(0,4);
//创建基于SHA-1的算法消息摘要对象
MessageDigest sha1 = MessageDigest.getInstance("SHA-1");
sha1.update(password.getBytes());//原始密码
sha1.update(salt.getBytes());//盐值
//计算加密结果,SHA-1的输出结果为20个字节(40个字符)
String digestHex = HashTools.bytesToHex(sha1.digest());
System.out.println(digestHex);
}
}
MD5,SHA-1加密,利用工具类实现
//通过自定义工具类,完成对应加密处理
//md5加密
String md5 = HashTools.digestByMD5 ( "wysssm" );
//sha-1加密
String md5 = HashTools.digestByMD5 ( "wysssm" );
System.out.println("md5="+md5);
System.out.println("sha1="+sha1);
By Mr.GUGUGU