hmac



算法:

HMAC 需要一個加密用散列函數(表示爲 H)和一個密鑰 K。我們假設 H 是 一個將數據塊用一個基本的迭代壓縮函數來加密的散列函數。我們用 B 來表示數據塊的字長。(以上提到的散列函數的分割數據塊字長 B = 64),用 L 來表示散列函數的輸出數據字長(MD5中 L = 16 , SHA-1 中 L = 20)。鑑別密鑰的長度可以是小於等於數據塊字長的任何正整數值。應用程序中使用的密鑰長度若是比 B 大,則首先用使用散列函數 H 作用於它,然後用 H 輸出的 L 長度字符串作爲在 HMAC 中實際使用的密鑰。一般情況下,推薦的最小密鑰 K 長度是 L 個字長。(與 H 的輸出數據長度相等)。

我們將定義兩個固定且不同的字符串 ipad,opad:(‘i’,‘o’表示內部與外部) 

ipad = the byte 0x36 repeated B times
opad = the byte 0x5C repeated B times

計算‘text’的 HMAC:

H (K XOR opad, H (K XOR ipad, text))

計算步驟:

在密鑰 K 後面添加 0 來創建一個子長爲 B 的字符串。(例如,如果 K 的字長是 20 字節,B=60 字節,則 K 後會加入 44 個零字節0x00)
將上一步生成的 B 字長的字符串與 ipad 做異或運算
將數據流 text 填充至第二步的結果字符串中
用 H 作用於第三步生成的數據流
將第一步生成的 B 字長字符串與 opad 做異或運算
再將第四步的結果填充進第五步的結果中
用 H 作用於第六步生成的數據流,輸出最終結果

實現:基於MD5散列函數的hamc

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class HMac {
    private static int B = 64;
    static {
        try {
            B = MessageDigest.getInstance("md5").getDigestLength();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static byte[] HmacMD5(byte[] data, byte[] key) {
        if (key.length > B) {
            key = md5(key);
        }
        if (key.length < B) {
            byte[] newKey = new byte[64];
            for (int i = 0; i < B; i++) {
                if (i < key.length) {
                    newKey[i] = key[i];
                } else {
                    newKey[i] = 0x00;
                }
            }
            key = newKey;
        }
        byte[] ipad = new byte[B];
        byte[] opad = new byte[B];
        for (int i = 0; i < B; i++) {
            ipad[i] = 0x36;
            opad[i] = 0x5C;
        }
        // H (K XOR opad, H (K XOR ipad, text))
        byte[] K = new byte[B + data.length];
        for (int i = 0; i < B; i++) {
            K[i] = (byte) (key[i] ^ ipad[i]);
        }
        System.arraycopy(data, 0, K, B, data.length);//K = concat(k,data)
        data = md5(K);
        K = new byte[B + data.length];
        for (int i = 0; i < B; i++) {
            K[i] = (byte) (key[i] ^ opad[i]);
        }
        System.arraycopy(data, 0, K, B, data.length);//K = concat(k,data)
        return md5(K);
    }

    public static byte[] md5(byte[] data) {
        try {
            return MessageDigest.getInstance("md5").digest(data);
        } catch (final NoSuchAlgorithmException e) {
            throw new IllegalArgumentException(e);
        }
    }

}



發佈了126 篇原創文章 · 獲贊 59 · 訪問量 47萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章