網站首頁 編程語言 正文
哈希算法(Hash)又稱摘要算法(Digest)
作用是:對任意一組輸入數據進行計算,得到一個固定長度的輸出摘要。
哈希算法最重要的特點就是:
1.相同的輸入一定得到相同的輸出
2.不同的輸入大概率得到不同的輸出(可能會出現哈希碰撞,即不同輸出得到相同輸出)
哈希算法可以驗證原始數據是否被篡改,所以可以用來校驗下載文件,另外還可以用來存儲用戶密碼。
但因為相同的輸入通過哈希算法會得到相同的結果,所以簡單的密碼和口令在數據泄露容易遭到彩虹表攻擊(彩虹表即常用口令和他們MD5的對照表),數據泄露時常用口令很容易通過MD5被反查到。
當然我們可以對要進行哈希算法的口令額外增加隨機數,這個方法稱為“加鹽”,可以有效增加密碼和口令的安全性。
常用的哈希算法
算法 | ?輸出長度(位) | 輸出長度(字節) |
MD5?? | 128bits | 16bytes |
SHA-1 | 160bits | 20bytes |
RipeMD-160 | 160bits | 20bytes |
SHA-256 | 256bits | 32bytes |
SHA-512 | 512bits | 64bytes |
以MD5算法為例,在用MD5進行編碼時,首先需要根據編碼方式創建MessageDigest實例,然后調用update(byte[ ])更新原始數據,再通過digest()方法獲得byte[ ]形式的加密后的結果 ,最后轉化為十六進制的字符串。
具體代碼如下:
package com.gjh.demo02;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Text02 {
public static void main(String[] args) {
try {
String password="wbjxxmynhmyzgq123";
//獲取基于MDS加密算法的工具對象
MessageDigest digest=MessageDigest.getInstance("MD5");
//更新原始數據
digest.update(password.getBytes());
//獲取加密后的結果
byte[] resultByteArray=digest.digest();
System.out.println(resultByteArray);
System.out.println(resultByteArray.length);
StringBuilder result1=new StringBuilder();
for(byte resultByte:resultByteArray) {
result1.append(String.format("%02x", resultByte));
}
System.out.println(result1);
System.out.println(result1.length());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
可以看到以下是它的實現結果:
由于轉化為十六進制的字符串時,我們設置一個字節占2個字符,所以得到的字符串長度為32個字符
SHA-1算法的編碼方式與MD5完全一致,只需要在創建MessageDigest實例時將編碼方式改為"SHA-1"
以下為MD5和SHA-1算法結果長度的對比的代碼:
package com.gjh.demo02;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
public class Text04 {
public static void main(String[] args) {
String password="wxshfg";
String salt="acsvd";
try {
MessageDigest digest=MessageDigest.getInstance("SHA-1");
MessageDigest digest1=MessageDigest.getInstance("MD5");
digest.update(password.getBytes());
digest.update(salt.getBytes());
digest1.update(password.getBytes());
digest1.update(salt.getBytes());
byte[] result=digest.digest();
byte[] result1=digest1.digest();
System.out.println("使用SHA-1的byte數組result值");
System.out.println(result);
System.out.println(result.length);
System.out.println("使用MD5的byte數組result值");
System.out.println(result1);
System.out.println(result1.length);
StringBuilder sb=new StringBuilder();
for(byte b:result) {
sb.append(String.format("%02x", b));
}
StringBuilder sb1=new StringBuilder();
for(byte b1:result1) {
sb1.append(String.format("%02x", b1));
}
System.out.println("使用SHA-1的StringBuilder值");
System.out.println(sb);
System.out.println(sb.length());
System.out.println("使用MD5的StringBuilder值");
System.out.println(sb1);
System.out.println(sb1.length());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
?可以看到以下是它的實現結果:
Hmac算法
Hmac算法是一種基于密鑰的消息認證碼算法,是一種更安全的消息摘要算法。
Hmac算法總是和某種哈希算法配合起來用的。例如,我們使用MD5算法,對應的就是Hmac MD5算法,它相當于“加鹽”的MD5。
HmacMD5與MD5相比:
HmacMD5使用的key長度是64字節,更安全;
Hmac是標準算法,同樣適用于SHA-1等其他哈希算法;
Hmac輸出和原有的哈希算法長度一致。
在用HmacMD5進行編碼時,首先需要根據編碼方式創建KeyGenerator實例,KeyGenerator實例再調用generateKey()方法獲取秘鑰key,通過key.getEncoded()獲取秘鑰key的字節數組,再將其轉化為十六進制的字符串。
在加密過程,需要通過名稱HmacMD5獲取Mac實例,對Mac實例調用update(byte[ ])輸入要進行加密的數據,再調用Mac實例的doFinal()獲得最終的哈希值,再將其轉化為十六進制的字符串。
具體代碼如下:
package com.gjh.demo03;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.KeyGenerator;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
public class Text01 {
public static void main(String[] args) {
String password="nhmyzgq";
try {
//1.生成秘鑰
//2.秘鑰生成器keyGenerator
KeyGenerator keyGe=KeyGenerator.getInstance("HmacMD5");
//生成秘鑰
SecretKey key=keyGe.generateKey();
//獲取秘鑰key的字節數組(64)
byte[] ketByteArray=key.getEncoded();
System.out.println(ketByteArray);
System.out.println("秘鑰的長度"+ketByteArray.length+"字節");
StringBuilder sb=new StringBuilder();
for(byte b:ketByteArray) {
sb.append(String.format("%02x", b));
}
System.out.println("秘鑰的內容"+sb);
System.out.println(sb.length());
Mac mac=Mac.getInstance("HmacMD5");
mac.init(key);
//更新原始內容
mac.update(password.getBytes());
//加密
byte[] resultByteArray=mac.doFinal();
System.out.println("加密結果"+resultByteArray.length+"字節");
StringBuilder resultStr=new StringBuilder();
for(byte by:resultByteArray) {
resultStr.append(String.format("%02x", by));
}
System.out.println("加密結果:"+resultStr);
System.out.println("加密結果長度:"+resultStr.length());
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
?可以看到以下是它的實現結果:
除了通過Hmac計算的秘鑰,也可以通過指定的字節數組恢復秘鑰,恢復秘鑰的語句就是new SecretKeySpec(hkey, "HmacMD5")。
具體代碼如下:
package com.gjh.demo03;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import javax.crypto.Mac;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
public class Text02 {
public static void main(String[] args) {
String password="nhmyzgq";
try {
byte[] keyByteArray= {126, 49, 110, 126, -79, -5, 66, 34, -122, 123, 107, -63, 106, 100, -28, 67, 19, 23, 1, 23, 47, 63, 47, 109, 123, -111, -27, -121, 103, -11, 106, -26, 110, -27, 107, 40, 19, -8, 57, 20, -46, -98, -82, 102, -104, 96, 87, -16, 93, -107, 25, -56, -113, 12, -49, 96, 6, -78, -31, -17, 100, 19, -61, -58};
SecretKey key=new SecretKeySpec(keyByteArray ,"HmacMD5");
Mac mac=Mac.getInstance("HmacMd5");
mac.init(key);
mac.update(password.getBytes());
byte[] resultByteArray=mac.doFinal();
StringBuilder resultStr=new StringBuilder();
for(byte b:resultByteArray) {
resultStr.append(String.format("%02x", b));
}
System.out.println("加密結果"+resultStr);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (InvalidKeyException e) {
e.printStackTrace();
}
}
}
?BouncyCastle
BouncyCastle是一個提供了很多哈希算法和加密算法的第三方開源庫。它提供了很多Java標準庫沒有提供的哈希算法和加密算法,例如,RipeMD160哈希算法。
與MD5算法不同的是,我們要使用BouncyCastle提供的RipeMD160算法,需要先注冊BouncyCastle提供的通知類對象BouncyCastleProvider
具體代碼如下:
package com.gjh.demo;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Security;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider;
public class Text01 {
public static void main(String[] args) {
try {
//注冊BouncyCastle提供的通知類對象BouncyCastleProvider
Security.addProvider(new BouncyCastleProvider());
//獲取RipeMD160算法的“消息摘要對象”(加密對象)
MessageDigest msg=MessageDigest.getInstance("RipeMD160");
//更新原始數據
msg.update("hello".getBytes());
//獲取消息摘要(加密)
byte[] result=msg.digest();
//消息摘要的字節長度和內容
System.out.println(result); //160位=20字節
System.out.println(result.length);
//16進制內容字符串
String hex=new BigInteger(1,result).toString(); //20字節,40個字符,按一個字節占2個字符
System.out.println(hex);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}
}
}
原文鏈接:https://blog.csdn.net/qq_50587186/article/details/125899375
相關推薦
- 2022-06-09 ASP.NET?Core中的Options選項模式_基礎應用
- 2022-09-15 Python利用shutil實現拷貝文件功能_python
- 2022-07-21 nginx的禁止ip訪問的配置方法和不緩存html
- 2022-07-19 RPM命令和YUM命令用法
- 2022-04-04 前端小技巧:關閉瀏覽器時觸發事件
- 2022-07-21 React樣式沖突問題
- 2023-10-15 element-ui里el-progress:進度條問題的解決Invalid prop: custo
- 2022-10-11 golang游戲等資源壓縮包創建和操作方法_Golang
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支