簡體   English   中英

這是測試散列函數雪崩效應的正確方法嗎?

[英]Is this the correct way of testing the avalanche effect of a hash function?

我正在嘗試用 C 實現一個哈希表來豐富我對數據結構的理解。

有很多用於哈希表實現的哈希函數。

為了比較散列函數,有一個稱為雪崩效應測試的測試。

為了測試我目前擁有的哈希函數集,我用 Java 編寫了一個小程序:

    public static void testHashAvalanche() {
        Set<Long> collisionSet = new HashSet<>();
        // The input for the hash function with 128 bytes.
        byte[] bytes = new byte[128];
        long count = 0;
        long previous = 0;
        long totalAvalanche = 0;
        // Generate the inputs for hashing with a slight change of bit each time
        for (int i = 0; i < 128; i++) {
            // Byte value from 0 -> 255
            for (int j = 0; j < 256; j++) {
                long current = hash(bytes); // Any hash function with 64 bit output
                int avalanche = calculateAvalanche(previous, current);
                totalAvalanche += avalanche;
                bytes[i]++;
                count++;
                previous = current;
            }
        }
        System.out.println("Average Avalanche: " + (double) totalAvalanche / (double) count);
    }
    
    public static int calculateAvalanche(long a, long b) {
        long difference = a ^ b;
        return Long.bitCount(difference);
    }

我想知道這是否是一種正確的方法,或者還有其他方法來測試散列函數。

謝謝!

讓我們從快速觀察開始。 假設您正在散列 128 字節的值。 這意味着您正在對 1024 位長的輸入進行哈希處理。 有多少個不同的 1024 位數字? 嗯,第一位可以是零或一。 獨立地,第二位可以是零或一。 與此無關,第三位可以是零或一等。這意味着這些位的可能組合數是 2 × 2 × ... × 2,總共 1024 次,或 2 1024

就上下文而言,這個數字是驚人的 稱其為“天文數字”實際上是對這個數字的侮辱,因為可觀測宇宙中的原子數量大約為 2 300 您根本無法嘗試所有 2 1024種輸入組合以查看它們之間的差異。

那么你能做些什么呢? 一種選擇是選擇不同輸入的樣本,並為每個輸入計算與它們有一點不同的所有數字。 然后,將所有這些散列,查看有多少輸出位翻轉,並將這些數字平均在一起。 另一種選擇是選擇一個隨機值,在其中翻轉一些位,計算輸出散列的變化量,然后重復此過程以粗略估計散列在實踐中的變化情況。 或者您可以在“真實”輸入(可能來自數據庫或某處的值列表)上使用這些方法,對輸入進行“真實”編輯(對於某些定義,可能通過將一個值的哈希值與“相似”值的哈希值進行比較“類似”)。

您正在采取的方法是沿着這些路線的,但並不完全相同。 具體來說,您的方法通過維護一個字節數組來工作,循環瀏覽模式

0 0 0 0 ... 0 0
0 0 0 0 ... 0 1
0 0 0 0 ... 0 2
0 0 0 0 ... 0 3
0 0 0 0 ... 0 4
      ...
0 0 0 0 ... 1 0
0 0 0 0 ... 2 0
0 0 0 0 ... 3 0
0 0 0 0 ... 4 0
      ...

這有幾個問題。 首先,這些輸入可能不是可能輸入的良好代表性樣本。 (盡管在您的應用程序中散列這些類型的值可能很常見,在這種情況下您可以忽略這一點。^_^)

接下來的問題是,你改變一次一個字節,在一個時間,而不是一個 這可能是也可能不是問題,這取決於您要測量的內容。 如果您正在尋找單個字節級別的雪崩效應,這很好。 但是,如果您正在尋找單個級別的雪崩效應,這將不起作用。 例如,將一個字節從 15 (00001111) 滾動到 16 (00010000) 會更改 5 位。 通過使用格雷碼以一次翻轉一位的方式循環遍歷所有可能的字節,您可以保持當前一次修改一個字節的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM