消息摘要算法的主要特徵是加密過程不須要密鑰,而且通過加密的數據沒法被解密,只有輸入相同的明文數據通過相同的消息摘要算法才能獲得相同的密文.java
所以能夠對數據傳輸先後進行兩次消息摘要,相同的內容摘要必定相同.通常地,把對一個信息的摘要稱爲該消息的指紋或數字簽名。數字簽名是保證信息的完整性和不能否認性的方法。算法
常見的消息摘要算法有:數據庫
hash 算法:(一般也稱散列算法,是一種將任意長度的消息變成固定長度的消息摘要算法,不可逆)apache
Message Digest Algorithm 5,流行度極高,但目前被發現存在碰撞衝突風險; 數組
任意長度輸出爲128bit=16字節摘要安全
SHA 指Security Hash Algorithm,由美國國家安全局NSA設計的安全散列算法系列; ide
SHA1 輸出長度爲160bit=20字節摘要編碼
繼SHA1 出現的算法(屬於SHA-2類),安全性較SHA1更高; 加密
SHA256 輸出長度爲256bit=32字節摘要spa
MAC 算法
Message Authentication Code,消息認證碼算法,基於HASH算法之上,增長了密鑰的支持以提升安全性。
具體算法包括HmacMD5/HmacSHA1/HmacSHA256等,輸入包括數據及密鑰,輸出長度與HASH算法一致。
密鑰能夠是任意長度的數據
MessageDigest 類是一個引擎類,它是爲了提供諸如 SHA1 或 MD5 等密碼上安全的報文摘要功能而設計的.
大體的主要步驟
1.獲取MessageDigest對象
public static MessageDigest getInstance(String algorithm)//注意:算法名不區分大小寫。
2.更新報文摘要對象
計算數據的摘要的第二步是向已初始化的報文摘要對象提供數據。這將經過一次或屢次調用如下某個 update(更新)方法來完成:
public void update(byte input) public void update(byte[] input) public void update(byte[] input, int offset, int len)3.計算摘要
經過調用 update 方法提供數據後,程序就調用如下某個 digest(摘要)方法來計算摘要:
public byte[] digest() public byte[] digest(byte[] input) public int digest(byte[] buf, int offset, int len)編碼實現:
須要導入的依賴:
<dependency> <groupId>commons-codec</groupId> <artifactId>commons-codec</artifactId> <version>1.5</version> </dependency> <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15on</artifactId> <version>1.54</version> </dependency>
package com.fitc.soldier.service.common; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; import java.security.Security; import org.apache.commons.codec.binary.Hex; import org.bouncycastle.crypto.Digest; import org.bouncycastle.crypto.digests.MD4Digest; import org.bouncycastle.crypto.digests.MD5Digest; import org.bouncycastle.jce.provider.BouncyCastleProvider; public class MDdemo { private static final String CONTENT="惟夢想與好姑娘不可辜負"; public static void main(String[] args) throws NoSuchAlgorithmException { jdkMD5(CONTENT); jdkMD2(CONTENT); bcMD4(CONTENT); } /** * JDK 提供的MD5實現 * 做爲主要的應用 * */ public static void jdkMD5(String Content) { try { //注意:算法名不區分大小寫。例如,如下全部調用都是相等的: MessageDigest messageDigest = MessageDigest.getInstance("MD5"); // 使用MD5算法對消息摘要(使用digest(byte[])的重載方法update 初始化原始數據) byte[] digest = messageDigest.digest(Content.getBytes()); // 爲了使摘要的結果以String 方式打印 便於對比 String encodeHexString = Hex.encodeHexString(digest); System.out.println("JDK 的MD5 摘要算法:" + encodeHexString); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * JDK 提供的MD2實現 * */ public static void jdkMD2(String Content) { try { MessageDigest messageDigest = MessageDigest.getInstance("MD2"); // 使用MD5算法對消息摘要 byte[] digest = messageDigest.digest(Content.getBytes()); // 爲了使摘要的結果以String 方式打印 便於對比 String encodeHexString = Hex.encodeHexString(digest); System.out.println("JDK 的MD2 摘要算法:" + encodeHexString); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } } /** * bc支持的MD4 * @throws NoSuchAlgorithmException */ public static void bcMD4(String Content) throws NoSuchAlgorithmException { // Security.addProvider(new BouncyCastleProvider()); // MessageDigest digest=MessageDigest.getInstance("MD4"); // byte[] digest2 = digest.digest(Content.getBytes()); // System.out.println(" bcMD4摘要算法:" + Hex.encodeHexString(digest2)); Digest digest=new MD4Digest(); // 初始化 digest.update(Content.getBytes(), 0, Content.getBytes().length); int digestSize = digest.getDigestSize(); // 定義摘要後的二進制數據 接收數組 byte[] md4Byte=new byte[digestSize]; // 對消息進行摘要 第二個參數 插入數據的偏移量 即從什麼位置插入 digest.doFinal(md4Byte, 0); System.out.println(" bcMD4摘要算法:" + Hex.encodeHexString(md4Byte)); } }
MD算法的應用場景:
對於用戶的密碼數據,在持久化時使用明文存儲不符合安全性的要求,此時能夠對密碼進行摘要算法而後再進行持久化.在此引用慕課網的教程圖片:
在註冊時存入數據庫的是密碼的摘要,在登錄時對登陸的密碼進行摘要而後對比數據庫中存儲的摘要判斷是否登陸成功.
/** * JDK 提供的SHA1等實現 * 做爲主要的應用 * */ public static void jdkSHA1(String Content) { try { //SHA-1 ,SHA-224,SHA-256 .... MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); //初始化參數數據 messageDigest.update(Content.getBytes());; // 使用SHA1算法對消息摘要 byte[] digest = messageDigest.digest(); // 爲了使摘要的結果以String 方式打印 便於對比 String encodeHexString = Hex.encodeHexString(digest); System.out.println("JDK 的SHA1 摘要算法:" + encodeHexString); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } }
對於其餘SHA算法大同小異,在此再也不贅敘.
MAC(也成HMAC)算法與MD以及SHA算法相比,在兼容兩種算法的基礎上加入了密鑰.
在使用密鑰時,須要瞭解幾個類:
keyGenerator:祕鑰生成器,也就是更具算法類型隨機生成一個祕鑰,例如HMAC,因此這個大部分用在非可逆的算法中.
KeyPairGenerator:祕鑰對生成器,也就是能夠生成一對祕鑰,也就是公鑰和私鑰,因此大部分使用在非對稱加密中
public static void hmac(String content) throws NoSuchAlgorithmException, InvalidKeyException{ /* * 根據算法名稱獲取密鑰生成器 */ KeyGenerator keyGenerator=KeyGenerator.getInstance("HmacMD5"); //生成密鑰 SecretKey generateKey = keyGenerator.generateKey(); //還原密鑰 // SecretKey restoregenerateKey=new SecretKeySpec(generateKey.getEncoded(), "HmacMD5"); /** * 建立Mac對象 */ Mac mac=Mac.getInstance(generateKey.getAlgorithm()); /** * 初始化 */ mac.init(generateKey); byte[] doFinal = mac.doFinal(content.getBytes()); System.out.println("HmacMD5 :"+Hex.encodeHexString(doFinal)); }
應用場景假設:
甲乙雙方進行數據交換能夠採起以下流程完成
一、甲方向乙方公佈摘要算法(就是指定要使用的摘要算法名)
二、甲乙雙方按照約定構造密鑰,雙方擁有相同的密鑰(通常是一方構造密鑰後通知另一方,此過程不須要經過程序實現,就是雙方約定個字符串,可是這個字符串可不是隨便設定的,也是經過相關算法獲取的)
三、甲方使用密鑰對消息作摘要處理,而後將消息和生成的摘要消息一同發送給乙方
四、乙方收到消息後,使用甲方已經公佈的摘要算法+約定好的密鑰 對收到的消息進行摘要處理。而後比對本身的摘要消息和甲方發過來的摘要消息。甄別消息是不是甲方發送過來的