1. 程式人生 > >Java如何獲取MD5值

Java如何獲取MD5值

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 值的實現方式。

   /**
     * 獲取String的MD5值
     *
     * @param info 字串
     * @return 該字串的MD5值
     */
    private static String getMD5(String info) {
        try {
            //獲取 MessageDigest 物件,引數為 MD5 字串,表示這是一個 MD5 演算法(其他還有 SHA1 演算法等):
MessageDigest md5 = MessageDigest.getInstance("MD5"); //update(byte[])方法,輸入原資料 //類似StringBuilder物件的append()方法,追加模式,屬於一個累計更改的過程 md5.update(info.getBytes("UTF-8")); //digest()被呼叫後,MessageDigest物件就被重置,即不能連續再次呼叫該方法計算原資料的MD5值。可以手動呼叫reset()方法重置輸入源。 //digest()返回值16位長度的雜湊值,由byte[]承接 byte[] md5Array = md5.digest(); //byte[]通常我們會轉化為十六進位制的32位長度的字串來使用,本文會介紹三種常用的轉換方法 return bytesToHex1(md5Array); } catch (NoSuchAlgorithmException e) { return ""; } catch (UnsupportedEncodingException e) { return ""; } } @NonNull private static String bytesToHex1(byte[] md5Array) { StringBuilder strBuilder = new StringBuilder(); for (int i = 0; i < md5Array.length; i++) { int temp = 0xff & md5Array[i];//TODO:此處為什麼新增 0xff & ? String hexString = Integer.toHexString(temp); if (hexString.length() == 1) {//如果是十六進位制的0f,預設只顯示f,此時要補上0 strBuilder.append("0").append(hexString); } else { strBuilder.append(hexString); } } return strBuilder.toString(); } //通過java提供的BigInteger 完成byte->HexString private static String bytesToHex2(byte[] md5Array) { BigInteger bigInt = new BigInteger(1, md5Array); return bigInt.toString(16); } //通過位運算 將位元組陣列到十六進位制的轉換 public static String bytesToHex3(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:

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 "";
}