MD5 簡介,及其在 Java 中的實現方式

2021-02-20 安卓筆記俠

MD5,Message Digest Algorithm 5,是一種被廣泛使用的信息摘要算法,可以將給定的任意長度數據通過一定的算法計算得出一個 128 位固定長度的散列值。如百科介紹,MD5 具有如下特點:

壓縮性:任意長度的原數據,其 MD5 值都是固定的,即 128 位;

易計算:計算原數據的 MD5 值是一個比較容易的過程;

抗修改:原數據的任意改動,所得到的 MD5 值都是迥然不同的;

防碰撞:這一點要特別介紹一下。MD5 使用的是散列函數(也稱哈希函數),一定概率上也存在哈希衝突(也稱哈希碰撞),即多個不同的原數據對應一個相同的 MD5 值。不過,經過 MD4、MD3 等幾代算法的優化,MD5 已經充分利用散列的分散性高度避免碰撞的發生。

可以看出,MD5 是一種不可逆的算法,也就說,你無法通過得到的 MD5 值逆向算出原數據內容。正是憑藉這些特點,MD5 被廣泛使用。

比如,客戶端與伺服器的 HTTP 通信,通信雙方可以將報文內容做一個 MD5 計算,並將計算所得 MD5 值一併傳遞給彼此,這樣,接收方可以通過對報文內容再次做 MD5 計算得到一個 MD5 值,與傳遞報文中的 MD5 值做比較,驗證數據是否完整,或者是否中途被攔截篡改過。

再比如,網絡雲盤中的文件秒傳功能也運用到 MD5 算法。伺服器存儲文件的時候,同時記錄每一個文件的 MD5 值,不同文件對應著不同的 MD5 值。這樣,遇到用戶上傳文件時,將上傳文件的 MD5 值與伺服器上所有存儲的 MD5 值做比較,如果相同,則說明用戶上傳的文件已經在伺服器存有。這樣,只需要在資料庫表中添加一個記錄,映射到對應的文件,而不用重複上傳,實現所謂秒傳的功能。

當然,這只是常見的兩個例子,MD5 的用途大有所在。值得注意的是,嚴格意義上來講,MD5 以及 SHA1 並不屬於加密算法,也不屬於籤名算法,而是一種摘要算法,用於數據完整性校驗等。

了解完基本的 MD5 概念,再來看看 Java 語言中計算 MD5 值的實現方式。

第一步,獲取 MessageDigest 對象,參數為 MD5 字符串,表示這是一個 MD5 算法(其他還有 SHA1 算法等):

MessageDigest md5 = MessageDigest.getInstance("MD5");

第二步,輸入原數據,參數類型為 byte[] :

注意:update() 方法有點類似 StringBuilder 對象的 append() 方法,採用的是追加模式,屬於一個累計更改的過程,比如:

md5.update(new byte[]{'a', 'b'});
md5.update(new byte[]{'c', 'd'});

md5.update(new byte[]{'a', 'b', 'c', 'd'});

是等效的,計算結果相同。

第三步,計算 MD5 值:

String resultArray = md5.digest();

注意:digest() 方法被調用後,MessageDigest 對象就被重置,也就是說你不能緊接著再次調用該方法計算原數據的 MD5 值。當然,你可以手動調用 reset() 方法重置輸入源。

digest() 方法返回值是一個字節數組類型的 16 位長度的哈希值,通常,我們會轉化為十六進位的 32 位長度的字符串來使用,可以利用 BigInteger 類來做這個轉化:

BigInteger bigInt = new BigInteger(1, resultArray);
String resultStr = bigInt.toString(16);

當然,還有很多其它方式也能實現字節數組到十六進位的轉換,比如通過位運算:

public static String byteArrayToHex(byte[] byteArray) {
char[] hexDigits = {'0','1','2','3','4','5','6','7','8','9', 'A','B','C','D','E','F' };
char[] resultCharArray =new char[byteArray.length * 2];
int index = 0;
for (byte b : byteArray) {
resultCharArray[index++] = hexDigits[b>>>4 & 0xf];
resultCharArray[index++] = hexDigits[b & 0xf];
}
return new String(resultCharArray);
}

通過這層轉換,得到的 MD5 值便是一個長度為 32 位的十六進位字符串,方便使用,類似這樣:

301d61853fc9ce94bbfb55b56c218d06

有了以上這些基礎知識,再來看看如何將文件轉化為一個 MD5 字符串:

public static String fileToMD5(String path){
try {
FileInputStream fis = new FileInputStream(path);
MessageDigest digest = MessageDigest.getInstance("MD5");
byte[] buffer = new byte[1024];
int len;
while ((len = fis.read(buffer)) != -1) {
digest.update(buffer, 0, len);
}
fis.close();
BigInteger bigInt = new BigInteger(1, digest.digest());
return bigInt.toString(16);
} catch (IOException | NoSuchAlgorithmException e){
e.printStackTrace();
}
return "";
}

注意:文件的大小直接影響字節流的讀取速度,間接影響這裡 MD5 的計算時長。Java 語言提供有多種方式讀取文件,除了上面用到的 FileInputStream 這種順序讀取的 API 類,還有採用隨機讀取方式的 RandomAccessFile 類等。關於各種讀取方式的效率,推薦大家閱讀這篇文章:

相關焦點

  • 概述Java中的數據結構是什麼及其內部實現原理
    那麼我該如何向數組中刪除一個元素呢這是我剛剛學習java時寫的一小段代碼,它用於刪除數組指定下標的元素,邏輯就是將要刪除的下標置換到數組尾部然後縮減數組長度,添加也是同樣的方法,總之是非常的麻煩,那麼對數組這種結構可以歸納為數組是一種被創建時長度固定,難增刪的數據結構,但是它由於有下標作為索引所以能夠快速定位到指定下標的元素,同時java.util.Arrays
  • Python 中 MD5 哈希函數的實現
    Python中的MD5哈希與md5相關的功能示例1:在Python中列印等效於MD5哈希的字節示例2:在Python中列印MD5哈希的十六進位等效項示例3:Python MD5文件校驗輸出與說明示例4:使用Python在MD5中編碼字符串輸出與說明示例5:在Python中計算文件的MD5哈希
  • Python 中 MD5 加密
    是計算機廣泛使用的雜湊算法之一(又譯摘要算法、哈希算法),主流程式語言普遍已有 MD5 實現。將數據(如漢字)運算為另一固定長度值,是雜湊算法的基礎原理,MD5 的前身有 MD2、MD3 和 MD4。MD5 的作用是讓大容量信息在用數字籤名軟體籤署私人密鑰前被"壓縮"成一種保密的格式(就是把一個任意長度的字節串變換成一定長的十六進位數字串)。
  • Java實現OAuth2.0授權碼方式
    Java實現OAuth2.0授權碼方式前面介紹了OAuth2.0和授權方式,可以參考以下文章:來驗證OAuth2.0授權方式的授權碼式,我們Spring Cloud的OAuth來實現認證和資源伺服器,以下是Web Security的配置。
  • CTF中關於md5的一些總結
    前言最近打了挺多ctf,碰到挺多關於md5的一些問題,或者一些變種的題目,雖然已經是爛大街的問題了,但是還是需要總結一下,方便下次比賽可以直接用腳本CTF中的一些案例案例1——ciscn2020初賽——easytrick<?
  • Java認證:Java編程中實現中文排序
    Java認證:Java編程中實現中文排序  第一種情況:  Comparator cmp = Collator.getInstance(java.util.Locale.CHINA);  String[] arr = { 「張三」, 「李四」, 「王五」, 「劉六」 };
  • JAVA開發中常用的四種加密方法
    上一篇:這300G的Java資料是我師傅當年給我的,免費分享給大家來源:http://suo.im/4zqd5z作者:愛編程的浪子一、工具類md5加密工具類base64加密工具類Bcrypt工具類二、加密測試MD5加密測試base64加密測試SHA加密測試BCrypt加密測試一、工具類1. md5加密工具類package 加密Tester.util;import java.security.MessageDigest
  • 一種基於Md5算法的改進加密方法
    對信息系統或者網站系統來說,MD5算法主要用在用戶註冊口令的加密,對於普通強度的口令加密,可以通過以下三種方式進行破解:(1)在線查詢密碼。一些在線的MD5值查詢網站提供MD5密碼值的查詢,輸入MD5密碼值後,如果在資料庫中存在,那麼可以很快獲取其密碼值。(2)使用MD5破解工具。網絡上有許多針對MD5破解的專用軟體,通過設置字典來進行破解。
  • md5到md5破解的一些科普
    看到網上一些對於md5的介紹還有對於當初王小雲所做的破解有很多的誤解,或者說不理解,然後覺得對於這些事情只要說明白還是比較好理解的說。首先md5其實就是一種hash,或者叫散列函數,有的地方叫雜湊函數,都是一個東西啦,其實他就是一種映射,而平常最常見的就是說md5是不可逆的,為什麼不可逆呢,有人就說就是像有些函數沒有反函數那樣了,其實還是有點抽象,考慮md5是多對一的映射,也就是說很多不同的經過md5變換之後可能會是相同的,那麼既然多對一,自然是不可逆啦╮(╯▽╰)╭,你怎麼會知道他到底是由哪個變換過來的呢。
  • C Sharp程式語言如何實現MD5加密的一個實例分享
    不是的,md5是一種信息摘要算法,它可以從一個字符串或一個文件中按照一定的規則生成一個特殊的字符串,這個特殊的字符串就被稱之為摘要,我理解就是從文件中摘一些信息片段加工而來,並且一個文件所對應的MD5摘要是固定的,當文件內容變化後,其MD5值也會不一樣,雖然理論上來說也有可能會一樣,但概率極小,因此,在應用中經常使用MD5值來驗證一段數據有沒有被篡改。下面用一個實例實現一個簡單的MD5加密練習。
  • JAVA異常及其異常處理方式
    比如說,你的代碼少了一個分號,那麼運行出來結果是提示是錯誤 java.lang.Error;如果你用System.out.println(100/0),那麼你是因為你用0做了除數,會拋出 java.lang.ArithmeticException 的異常。
  • Java Web安全 || Java基礎 · Java IO/NIO多種讀寫文件方式
    使用FileInputStream實現文件讀取Demo:package com.anbai.sec.filesystem;import java.io.= -1) { // 截取緩衝區數組中的內容,(bytes, 0, a)其中的0表示從bytes數組的 // 下標0開始截取,a表示輸入流read到的字節數。
  • JAVA學習之路(總結)--基礎篇二
    5年以上公司也只招中高級軟體工程師了,能力強的基本上能做架構師,那就是另一個薪資水平了。>簡介:API文檔是我們用來了解JDK中提供的類庫,我們可以先通過索引輸入並找到我們需要了解的類,而後我們就可以方便的了解該類的作用。
  • Java類隔離加載實現原理是什麼?
    到了運行的時候,默認情況下一個項目的所有類都是用同一個類加載器加載的,所以不管你依賴了多少個版本的 C,最終只會有一個版本的 C 被加載到 JVM 中。當 B 要去訪問 Log.error,就會發現 Log 壓根就沒有 error 方法,然後就拋異常java.lang.NoSuchMethodError。這就是類衝突的一個典型案例。
  • 使用Java API在Jedis中實現DAO設計模式
    在本文中,我們將學習Jedis Java客戶端中的DAO設計模式和實現。DAO模式被實現為客戶端應用程式和資料庫之間的一層。客戶端應用程式不必依賴基礎資料庫交互API(低級)。Redis資料庫中存儲的數據被建模為Domain對象(POJO類),它將僅具有getter和setter方法,客戶端應用程式僅知道域對象和高級API。
  • Java資料庫連接性簡介
    在您的文本編輯器中,粘貼清單1中所示的代碼。調用此文件WhatIsJdbc.java。Java開發者工具包簡介」。)一旦有了基本的Java程序,就可以包括JDBC庫。將清單2中的代碼粘貼到簡單Java程序的開頭。清單2. JDBC導入importjava.sql.
  • Java加密與解密:消息摘要算法MD5
    在這個算法中,我們仍需對信息進行數據補位。不同的是,這種補位使其信息的字節長度加上448個字節後成為512的倍數(信息字節長度mod 512 =448)。此外,關於MD4算的處理和MD2算法有很大的差別。但最終仍舊會獲得一個128為的散列值。
  • Java 中 Comparable 和 Comparator 比較
    Comparable 簡介Comparable 是排序接口。若一個類實現了Comparable接口,就意味著「該類支持排序」。此外,「實現Comparable接口的類的對象」可以用作「有序映射(如TreeMap)」中的鍵或「有序集合(TreeSet)」中的元素,而不需要指定比較器。
  • Java中加載資料庫驅動的方式有幾種?背後的原理是什麼?
    1、Class.forName()加載這是最常見的一種方式,也是從早期沿用下來的方式。下面看一下在這背後發生的事情。Driver接口先來了解下java.sql.Driver接口,java.sql.Driver是所有JDBC驅動程序需要實現的接口。這個接口是提供給資料庫廠商使用的,不同廠商實現該接口的類名是不同的,例如MySQL 8.x的JDBC驅動的類名是:com.mysql.cj.jdbc.Driver。
  • Java中的Filter過濾器詳解
    Filter簡介 Filter也稱之為過濾器,它是Servlet技術中最實用的技術,WEB開發人員通過Filter技術,對web伺服器管理的所有web資源:例如Jsp, Servlet, 靜態圖片文件或靜態 html