2009-05-27 111 views
3

我正在開發一個.NET 3.5項目,我需要一個32位散列值。 .NET密碼學類中似乎沒有任何方法返回32位散列(MD5是128位,SHA1是160位等)。我實現了一個CRC32類,但是我發現已經存在的SHA1和MD5哈希函數要快得多。160位SHA1哈希的前32位是CRC32哈希的可接受替代嗎?

使用SHA1散列函數會不會有任何問題(即增加衝突的可能性),並將前32位存儲爲我的散列值?

+2

你在做什麼,你不能存儲整個20個字符的SHA-1哈希?另外,CRC32不是一個散列,它是一個傳輸錯誤檢測機制,所以如果你需要錯誤檢測,散列並不是真正的方法。 – jmucchiello 2009-05-27 13:54:30

+0

爲節省空間,選擇了4字節散列。哈希將用於校驗來自監控設備的數據塊,並且可能會有數十萬個數據塊。我們會看到,也許存儲整個事情不會是一個問題。 你說了一些有趣的東西。 「傳輸錯誤檢測機制」和哈希之間的區別究竟是什麼?密碼強度(這個特定的應用程序不需要)? – raven 2009-05-27 14:01:00

+0

無恥的自我插件:cmdhashgen支持CRC32並且源自HashAlgorithm,所以它可以像其他人一樣使用,請檢查Crc32.cs:http://cmdtools.codeplex.com/ – 2009-05-27 14:16:50

回答

6

除非你想CRC32的額外功能(線性代碼),你應該罰款將輸出切割爲32位。

無論切割的一些加密散列函數的輸出會傷害其安全相對於抗碰撞是一個開放的研究問題(如果我記錯存在「非自然」構造的例子)。但NIST(可能經過NSA的批准)無論如何都使用切割技術從SHA-256獲取SHA-224(請參閱article about SHA in wikipedia)。

編輯:CRC32允許檢測(也許是正確的)單比特錯誤,而加密哈希函數應該有屬性,你不能找到兩個具有相同散列值的輸入。

您是否知道「生日悖論」(請參閱​​wikipedia)?隨着32位校驗你希望得到的碰撞(即,相同的哈希值的兩個輸入)如果您有關於2^16個輸入,並且要湊更多的投入。 (重讀您的評論,這可能不是你的問題。)

0

如果你不打算將32位用於加密目的,那麼你應該沒問題。否則,我不會依賴於與整個散列具有相同分佈的第一個32位。

爲什麼你不能只使用更廣泛的可用哈希?

0

CRC32可能適合您的需求。這已在this question中討論過。

在截斷哈希基元方面,唯一大量使用的應用是用於生成密鑰的SSL/TLS Pseudo Random Function (PRF)。它使用HMAC的種子和標籤通過多次散列生成儘可能多的字節,然後截斷所需的字節數量。

至於您的具體問題,雖然,你可以閱讀哈希的輸出入的Int32的,然後異或它們放在一起,如果你是偏執狂:

static void Main() 
{ 
    int xorCrc = GetHashedCrc(new SHA1Cng(), new byte[] {0xDE, 0xAD, 0xBE, 0xEF}); 
} 

private static int GetHashedCrc(HashAlgorithm algorithm, byte[] bytesToHash) 
{ 
    byte[] hash = algorithm.ComputeHash(bytesToHash); 
    int totalInt32s = hash.Length/sizeof(int); 
    int result = 0; 
    for(int i = 0; i < totalInt32s; i++) 
    { 
     int currentInt = BitConverter.ToInt32(hash, sizeof(int)*i); 
     result = result^currentInt; 
    } 

    return result; 
} 
2

鑑於散列函數平均分配其輸入假設在它的共域中,假設它也將平均分配給它的任何子集似乎是合乎邏輯的。 但是,使用「本機」32位散列函數可能仍然是更好的選擇。也許更多的人可以爲我們提供一個比我的直覺更好的理由:)

1

你爲什麼不只是使用string.GetHashCode()。它旨在計算32位散列值,並在給定實際數據的情況下產生很少的衝突。當然,這並不安全,但你的問題並不包括這個要求。