信息摘要技術 - MD系列

MD算法是信息摘要三大算法中場景的一種,全稱:Message Digest算法,按照規範版本分爲MD2、MD4、MD5三種算法,目前最常用的是MD5版本算法。

MD家族發展歷史

  • 1989年,RSA發明人開發了MD2算法:
    • 1.對信息進行補位,信息的字節長度爲16的倍數;
    • 2.以一個16位的校驗和,追加到信息末尾;
    • 3.根據新的信息產生一個128位的散列值,得出MD2值;
  • 1990年,在MD2基礎上發展出MD4算法:
    • 1.和MD2一樣,仍然對信息進行補位,但是補位時要添加448個字節,變爲 512的倍數;
    • 2.仍對信息做散列,獲取一個128位的散列值,得出MD4值;
    • MD4的算法影響很大,比如MD5、SHA-1、Ripe-MD系列都是從MD4基礎上衍生出來的;
  • 1991年,MD4的創始人開發出MD5算法:
    • MD5算法是MD算法中最成熟的算法;
    • MD5算法最終也是產生一個128位的散列碼;
    • MD5效率比MD4慢,但是安全性更高;
    • 隨着目前計算資源的提升,MD5算法已經被攻破,有很多破譯軟件進行暴力破解,而且破解速度不斷提升;
    • 但是MD5算法對於安全性要求不是很高的場景下,仍然廣泛流行;

應用場景

信息摘要算法是不可逆的,所以信息摘要場景主要被用來驗證信息的完整性,防止信息被篡改,主要場景如下:

  • 驗籤:對要發送的數據做MD5(一般加slat)MD5值和數據一同發送,接收方接受數據做同樣的MD5計算,比較MD5值是否一致;
  • 敏感信息存儲:比如用戶密碼存儲上,一般都是存儲MD5值,更高一級的涉及是針對每個用戶生成一個隨機的slat,然後進MD5(passport + slat)計算,將這個值存儲到DB中。
  • Spring Security中即使用了敏感信息存儲的方式進行了實現;

MD5算法在線破解:http://www.dmd5.com

Java中算法實現

算法供應商選擇

選擇算法共贏上很大程度決定了API接口的使用方式,Java的加解密供應商主要有三個:Sun,Bouncy Castle和Commons Codec:

  • Sun:提供MD2和MD5算法支持,接口比較簡答,唯一麻煩的地方是沒有提供byte[]轉16進制字符串的方法;
  • Bouncy Castle:添加了對MD4算法的支持,使用JAVA SPI方式提供,或者自己的API,提供了十六進制的方法;
  • Commons Codec:對Sun的Api的封裝,支持多種形式參數,支持16進制字符串形式,一般優先推薦;

MessageDigest類

在Java中,MD系列算法以MessageDigest類來完成,具體的實現方式通過JAVA SPI機制註冊進去,該類採用策略模式設計。Java本身自JDK 1.6開始提供MD2和MD5算法的支持,使用起來很簡單。唯一有點麻煩的地方即JDK的Api返回的數據都是byte[],想要轉換爲字符串,還需要調用一個轉換爲16進制的方法,這個方法可以使用HexBin方法或者其他工具,也不復雜。

MD4算法 : JDK沒有提供MD4算法支持,需要尋找第三方支持。

在Java中安裝第三方算法包,可以通過Java的SPI機制,使用Secuirty.addProvider()方法加載第三方組件。

下面是Java的MD5使用方式:

public class MD5Test {

    public static void main(String[] args) throws NoSuchAlgorithmException {

        String input = "Test";
        byte[] data = input.getBytes();
        MessageDigest md = MessageDigest.getInstance("md5");
        byte[] rsBytes = md.digest(data);
        log(new String(HexBin.encode(rsBytes)));
    }

    private static void log(String msg) {
        System.out.println(msg);
    }

}

DigestInputStream類

如果需要以流的形式進行MD計算,比如對大文件進行MD5計算,可以使用配套類DigestInputStream類,示例代碼如下:

public class MDInputStreamTest {

    public static void main(String[] args) throws NoSuchAlgorithmException, IOException {

        // 待做消息摘要操作的原始信息
        byte[] input = "md5".getBytes();
        // 初始化MesssageDigest對象,將使用MD5算法
        MessageDigest md = MessageDigest.getInstance("MD5");
        // 構建DigestInputStream對象
        DigestInputStream in = new DigestInputStream(new ByteArrayInputStream(input), md);
        try {// 每次讀取一段信息,計算MD5值,這裏可以分次讀取然後記錄每次的MD5
            in.read(input, 0, input.length);
            // 獲取摘要信息
            byte[] rs = in.getMessageDigest().digest();
            log(new String(HexBin.encode(rs)));
        } finally {
            in.close();
        }

    }

    private static void log(String msg) {
        System.out.println(msg);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章