日本免费高清视频-国产福利视频导航-黄色在线播放国产-天天操天天操天天操天天操|www.shdianci.com

學無先后,達者為師

網站首頁 編程語言 正文

常見哈希算法、Hmac算法和BouncyCastle

作者:好的OK Txtcyvy 更新時間: 2022-08-15 編程語言

哈希算法(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

欄目分類
最近更新