哈希算法概念及特点
哈希算法(Hash)又称摘要算法(Digest),它的作用是:对任意一组输入数据进行计算,得到一个固定长度的输出摘要。
哈希算法最重要的特点就是:
●相同的输入一定得到相同的输出;
●不同的输入大概率得到不同的输出。
所以,哈希算法的目的:为了验证原始数据是否被篡改。
常见的哈希算法:::
算法 | 输出长度(位) | 输出长度(字节) |
MD5 | 128 bits | 16 bytes |
SHA-1 | 160 bits | 20 bytes |
RipeMD-160 | 160 bits | 20 bytes |
SHA-256 | 256 bits | 32 bytes |
SHA-512 | 512 bits | 64 bytes |
哈希碰撞
哈希碰撞指的是:
"AaAaAa".hashCode(); // 0x7460e8c0
"BBAaBB".hashCode(); // 0x7460e8c0
"通话".hashCode(); // 0x11ff03
"重地".hashCode(); // 0x11ff03
两个不同的输入得到了相同的输出
碰撞是不可避免的,是一定会出现的,因为输出的字节长度是固定的。
MD5和SHA-1
SHA-1也是一种哈希算法,它的输出是160 bits,即20字节。
在Java中使用SHA-1,和MD5完全一样,只需要把算法名称改为"SHA-1":
用MD5和SHA-1时,可以创建一个架包,然后再使用,会更加便捷!、
架包怎么创建嘞!
代码如下:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
//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);
}
//通过消息摘要对象,处理加密内容
private static String handler(String source) {
digest.update(source.getBytes());
byte[] bytes = digest.digest();
String hash = bytesToHex(bytes);
return hash;
}
//将字节数组转换为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();
}
}
怎么应用呢:
import java.security.NoSuchAlgorithmException;
//通过自定义工具类,完成对应加密处理
public class Demo09 {
public static void main(String[] args) throws NoSuchAlgorithmException {
//MD5加密
String md5 = HashTools.digestByMD5("wbjxxmy");
//sha-1加密
String sha1 = HashTools.digestBySHA1("wbjxxmy");
System.out.println("md5="+md5);
System.out.println("sha1="+sha1);
}
}
哈希算法的用途
1.校验下载的文件以及应用是否为正版。一般情况下,官方下载文件的地方会有一些MD5哈希值,然后我们只需要计算本地下载文件的哈希值,如果一样,证明没有问题,如果不一样,那二锅头可就不能保证你的文件应用是不是有问题了 !!
2.存储用户密码。可以防止彩虹表的攻击。预防彩虹表攻击的方法是什么嘞!EMMM...
加盐,没错就是salt,食用盐。但是作用可不一样哦。
具体代码如下:
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.UUID;
//通过随机加盐,解决彩虹表共计
public class Demo08 {
public static void main(String[] args) {
try {
//y原始密码
String password = "123456";
//产生随机的盐值
String salt = UUID.randomUUID().toString().substring(0,4);
//创建基于SHA-1算法的消息摘要
MessageDigest pwd = MessageDigest.getInstance("MD5");
pwd.update(password.getBytes());//原始密码
pwd.update(salt.getBytes());//盐值
//计算加密结果,
String aaa = HashTools.bytesToHex(pwd.digest());
System.out.println(aaa);
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
Hmac算法
HMAC算法 是一种基于密钥的报文完整性的验证方法。HMAC算法利用哈希运算,以一个密钥和一个消息为输入,生成一个消息摘要作为输出。其安全性是建立在Hash加密算法基础上的。它要求通信双方共享密钥、约定算法、对报文进行Hash运算,形成固定长度的认证码。通信双方通过认证码的校验来确定报文的合法性。HMAC算法可以用来作加密、数字签名、报文验证等。
具体应用代码如下:
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
//Hmac算法
public class Demo10 {
public static void main(String[] args) throws NoSuchAlgorithmException, InvalidKeyException {
String password = "wbjxxmy";
//获取HmacMD5秘钥生成器
KeyGenerator keyGen = KeyGenerator.getInstance("HmacMD5");
//1.生成秘钥
SecretKey key = keyGen.generateKey();
System.out.println("秘钥:"+Arrays.toString(key.getEncoded()));
System.out.println("秘钥长度(64字节):"+key.getEncoded().length);
System.out.println("秘钥:"+HashTools.bytesToHex(key.getEncoded()));
//2.使用秘钥,进行加密
//获取HMac加密算法对象
Mac mac = Mac.getInstance("HmacMD5");
mac.init(key);//初始化秘钥
mac.update(password.getBytes());//更新原始加密内容
byte[] bytes = mac.doFinal();//加密处理,并获取加密结果
String result = HashTools.bytesToHex(bytes);//加密结果处理成16进制字符串
System.out.println("加密结果16进制字符串"+result);
System.out.println("加密结果(字节长度16字节)"+bytes.length);
System.out.println("加密结果(字节长度32字节)"+result.length());
}
}
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class Demo11 {
public static void main(String[] args) {
//原始密码
String password = "wbjxxmy";
//秘钥(字节数组)
//byte[] keyBytes = {-6, 120, 7, 96, 30, -96, -58, 86, -70, 15, 106, -107, -3, 119, -48, -87, 27, -100, -45, 70, 77, -50, 1, 93, 114, 118, 65, -78, -71, 41, -121, 101, 15, -73, 14, 86, -97, 66, 9, 30, 43, 94, 117, -67, -29, 30, -119, 59, 6, -112, 48, 125, 4, -23, 107, 126, -14, 72, 106, 99, -106, -96, 70, 112};
//秘钥(字符串)
String keyStr = "451c60fff4f3c52e9f8e22e537bee82cb46f45e692a270d3728bbaf23550cb82af0baf1ddad3ec19e7893d13f18a386439dbfb452d4810921b8aa50a2de5d8ac";
//f78a76fa7b8e2e79c19372ad2b7d7292
//用于保存秘钥:秘钥长度为64字节
byte[] keyBytes = new byte[64];
for (int i = 0, k = 0; i < keyStr.length(); i+=2 ,k++) {
String s = keyStr.substring(i,i+2);
keyBytes[k] = (byte) Integer.parseInt(s,16);//转换成16进制byte值
}
//恢复秘钥(字节数组)、
try {
SecretKey key = new SecretKeySpec(keyBytes,"HmacMD5");
//创建Hmac加密算法对象
Mac mac =Mac.getInstance("HmacMD5");
mac.init(key);//初始化秘钥
mac.update(password.getBytes());
String result = HashTools.bytesToHex(mac.doFinal());
//a69f35cc658225d18915cd0bf1a37115
System.out.println(result);
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalStateException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
使用第三方开源库提供的RipeMDR60消息摘要算法实现
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import java.util.Arrays;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
//使用第三方开源库提供的RipeMDR60消息摘要算法实现
public class Demo12 {
public static void main(String[] args) throws NoSuchAlgorithmException {
//注册BouncyCastlenBouncyCastleProvider通知类
//将提供的消息摘要算法注册至Security
Security.addProvider(new BouncyCastleProvider());
//获取RipeMD160算法的“消息摘要对象”(加密对象)
MessageDigest ripeMd160 = MessageDigest.getInstance("RipeMD160");
//更新原始数据
ripeMd160.update("wbjxxmy".getBytes());
//获取消息摘要(加密)
byte[] result = ripeMd160.digest();
//消息摘要的字节长度和内容
System.out.println("加密结果(字节长度):"+result.length);//20字节=40个字符
System.out.println("加密结果(字节内容):"+Arrays.toString(result));
//16进制内容字符串
String hex = new BigInteger(1, result).toString(16);
System.out.println("加密结果(字符串长度):"+hex.length());//20字节=40个字符
System.out.println("加密结果(字符串内容):"+hex);
}
}
以上就是二锅头今天整理的哈希算法的相关知识还有代码了。。。
如果对你有帮助,记得支持二锅头,一键三连哦!!!