計算 位元組陣列、字串與檔案的 MessageDigest 值 (MD5、SHA-1、SHA-256…)
Message Digest 中文是「訊息摘要」,就是將訊息透過特別的演算法計算,得到一組可以代表這段訊息的特徵值。
簡單來說,就類似每個人身上都有不同的指紋,而指紋就是這個人的特徵。
而常見的 Message Digest 演算法,包含: MD5 與 SHA-1。
MD5 算出來的 Message Digest 是一串 128 bits 的訊息摘要,所以有 2^128 種組合;
SHA-1 算出來的 Message Digest 是一串 160 bits 的訊息摘要,所以有 2^160 種組合。
由於 Message Digest 演算法 (1) 計算時間很快 (2) 同一訊息特徵值都相同,所以常常拿來應用。
例如:拿來當 (1) 密碼 與 SaltedString 的驗證 (2) 檔案下載的封包 checksum 驗證。
題外話,雖然 2005年「王小雲」已經找到「破解」MD5 與 SHA-1 的方法,但只是縮短碰撞時率的時間。
能夠讓 MD5 與 SHA-1 快速地找到 Message 本文,但是離破解密碼還有一段距離。
而之前艾小克「取得 MD5 (SHA1) 的三種方法」文章,談到 .Net 計算兩種 MessageDigest 的方法。
而本篇文篇範例,則是介紹使用 Java 來計算 位元組陣列、字串、檔案 的 MessageDigest 值。
目前在 Java SDK 6.0 中主要支援 MessageDigest Algorithm 有六種,
包含:MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512 在本篇範例中都會一一展示。
我們就直接看程式碼:
第 17 行,利用 MessageDigest.getInstance() 方法建立一個 MessageDigest 物件 messageDigest。
algorithm 參數則如同前言所提,包含以下六種:MD2、MD5、SHA-1、SHA-256、SHA-384、SHA-512
第 25 行,則是利用 MessageDigest 物件 messageDigest 的 update() 方法,計算 byte[] 物件 buffer 的 Message Digest 值。
第 26 行,則是利用 MessageDigest 物件 messageDigest 的 digest() 方法,取得 Message Digest 值,該值是以 byte[] 儲存。
第 28 – 33 行,則是迴圈計算每一個 byte 值,將每個 byte 值轉為 hex 字串表示。
1. 位元組陣列 的 MessageDiagest:
透過剛剛介紹自定 calculateMessagesDigest() 方法,我們就可以寫一個 getMessagesDigest() 方法,提供我們來方便地呼叫:
第 51 – 57 行,則是 algorithm 字串變數與內建的演算法做不分大小寫的字串比對,
如果是 Java 有支援的演算法才將 byte[] 型態 data 變數傳入剛剛 calculateMessagesDigest() 計算 MessageDigest hex 字串值。
2. 字串的 MessageDiagest:
第 40 – 46 行,則是 algorithm 字串變數與內建的演算法做不分大小寫的字串比對,
比較不同的是,我們必須將字串轉 byte[] 才能呼叫 calculateMessagesDigest() 方法,所以我們使用內建的字串物件 getBytes() 方法即可。
(如果有 Encoding 的問題,則帶入多載的 getBytes() 方法,傳入不同的 Charset 物件)
3. 檔案的 MessageDiagest:
由於 calculateMessagesDigest() 方法需要的參數是 byte[],所以我們比較將檔案轉換成 byte[]。
所以,第 62 行將 filePath 與 fileName 字串連接在一起,並建立 File 物件 file。
第 66 行,則是透過 File 物件 file 轉為 FileInputStream 物件 fis。
第 74 – 79 行,則是將 FileInputStream 物件 fis 的 byte[] 內容讀出並放入 byte[] 變數 data 中。
第 86 – 92 行,則是 algorithm 字串變數與內建的演算法做不分大小寫的字串比對,
將 byte[] 型態 data 變數傳入剛剛 calculateMessagesDigest() 計算 MessageDigest hex 字串值。
剛剛我們建立三個 getMessagesDigest() 多載的方法,現在我們就可以來測試使用:
第 17 行,我們建立一個字串陣列 algorithmsStrings ,儲存 Java 所有支援的 Message Digest 演算法。
第 19 –25 行,我們使用 for 迴圈去尋覽所有的 algorithmsStrings 字串值,並呼叫三個 getMessagesDigest() 多載的方法:
第 21 行,我們帶入不同的演算法,利用字串常數 “a”計算不同的 Message Digest 值。
第 22 行,我們帶入不同的演算法,利用 常數位元組陣列 97 (其實就是 a 的 ASCII碼) 計算不同的 Message Digest 值。
第 23 行,我們帶入不同的演算法,利用 檔案 /User/chhuang/Desktop 路徑下的 untitled.txt (其實內容只有 “a”) 計算不同的 Message Digest 值。
執行結果如下:
MD2 string : 32ec01ec4a6dac72c0ab96fb34c0b5d1
MD2 byte[] : 32ec01ec4a6dac72c0ab96fb34c0b5d1
MD2 file : 32ec01ec4a6dac72c0ab96fb34c0b5d1
MD5 string : 0cc175b9c0f1b6a831c399e269772661
MD5 byte[] : 0cc175b9c0f1b6a831c399e269772661
MD5 file : 0cc175b9c0f1b6a831c399e269772661
SHA-1 string : 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
SHA-1 byte[] : 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
SHA-1 file : 86f7e437faa5a7fce15d1ddcb9eaeaea377667b8
SHA-256 string : ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
SHA-256 byte[] : ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
SHA-256 file : ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb
SHA-384 string : 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31
SHA-384 byte[] : 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31
SHA-384 file : 54a59b9f22b0b80880d8427e548b7c23abd873486e1f035dce9cd697e85175033caa88e6d57bc35efae0b5afd3145f31
SHA-512 string : 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
SHA-512 byte[] : 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75
SHA-512 file : 1f40fc92da241694750979ee6cf582f2d5d7d28e18335de05abc54d0560e0f5302860c652bf08d560252aa5e74210546f369fbbbce8c12cfc7957b2652fe9a75