Java哈希散列算法簡介 - MD5 & SHA-512
在日常的開發工作中,我們常常會碰到這樣的一個場景:我們需要有一種可靠的行之有效的方法來檢驗跟判斷數據在傳輸過程當中的完整性。最常見的一種情況就是當我們傳輸文件的時候,由於網絡故障或者其他的一些因素,可能會出現我們下載下來的文件不完整,這給我們日常的開發和維護帶了一些難題;另外的一個較為常用的場景就是:有沒有一種行之有效的方法讓我們可以很方便的判斷服務器上的文件是不是有最新的數據更新,比如我們現在的移動Hybird App開發,我們經常會發布一些client pack的數據更新,那么我們在每次打開App應用的時候就必須先要檢驗服務器端是否有最新的更新需要下載,以便我們及時使用最新的App功能。
針對於以上這些應用場景,我們最常使用的方法便是使用安全哈希算法MD5根SHA-512,它們具有以下的特點:
- 唯一性:同一個數據只有同一個哈希值
-可靠性:兩個不同的數據有不同的哈希值 (MD5已被在某些特例下存在相同得值)
-不可逆性:不可以通過哈希值反推輸入的原值
兩個算法都具有極高的安全性,但是相比較而言,SHA-512算法擁有更高的安全級別,因此,此算法已被大部分的人所采用。
以下便是這兩種算法的具體實現代碼:
package com.andycbluo.secure.checksum.util; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; public class SecureUtil { private final String SHA512 = "SHA-512"; private static SecureUtil _instance = null; private SecureUtil() {} /** * * @return */ public static SecureUtil getInstance() { return _instance; } /** * * @param data * @return */ public String generateChecksum(String data) { return generateChecksum(data, SHA512); } /** * * @param data * @param algorithom * @return */ public String generateChecksum(String data, String algorithom) { String checksum = null; try { MessageDigest instance = MessageDigest.getInstance(algorithom); instance.update(data.getBytes("UTF-8")); checksum = convertBytes2String(instance.digest()); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } return checksum; } /** * * @param data * @return */ private String convertBytes2String(byte[] data) { StringBuffer sb = new StringBuffer(); for(int i = 0; i < data.length; i++) { sb.append(Integer.toString(data[i] & 0xFF + 0x100, 16).substring(1)); } return sb.toString(); } /** * * @param filePath * @return */ public String generateFileChecksum(String filePath) { return generateFileChecksum(filePath, SHA512); } /** * * @param filePath * @param algorithom * @return */ public String generateFileChecksum(String filePath, String algorithom) { String checksum = null; MessageDigest instance; try { instance = MessageDigest.getInstance(algorithom); InputStream fis = new FileInputStream(new File(filePath)); byte[] blob = new byte[1024]; int numRead; do { numRead = fis.read(blob); if (numRead > 0) { instance.update(blob, 0, numRead); } } while (numRead != -1); checksum = convertBytes2String(instance.digest()); fis.close(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } return checksum; } /** * */ static { _instance = new SecureUtil(); } }
我們可以通過一個簡單的用例來窺探MD5根SHA-512的輸出結果:
package com.andycbluo.secure.checksum; import com.andycbluo.secure.checksum.util.SecureUtil; public class TestRunner { private static final String TEST_DATA = "This is a testing data : 123456789"; private static final String FILE_PATH = "<Replace Your File Path Name Here>"; public static void main(String[] args) { System.out.println("SHA-512 : " + SecureUtil.getInstance().generateChecksum(TEST_DATA)); System.out.println("MD5 : " + SecureUtil.getInstance().generateChecksum(TEST_DATA, "MD5")); System.out.println("File SHA-512 : " + SecureUtil.getInstance().generateFileChecksum(FILE_PATH)); System.out.println("File MD5 : " + SecureUtil.getInstance().generateFileChecksum(FILE_PATH, "MD5")); } }
以下就是本地的輸出結果: