合適的 16 位校驗和?
我正在編寫一個玩具1傳輸協議,並且我正在嘗試實現一個功能:
- 每個數據包中都包含一個 16 位校驗和。
- 如果數據很大,完整性很重要,或者其他什麼(創建這個主要是為了好玩),這個校驗和可以擴展到 48 位。
- 此校驗和旨在防止錯誤,而不是堅定的攻擊者。
我最初的想法是使用眾所周知的算法,例如 MD5/SHA 2,並簡單地取第一個/最後一個 16/48 位。這提出了幾個問題:
- 簡單地採用校驗和的“子字元串”會產生什麼後果?我可能天真地假設它只會增加碰撞的可能性。
- 是否有任何理由更喜歡使用最後x位而不是前x位,反之亦然?
- 當像這樣截斷校驗和時,SHA 實際上是否比 MD5 執行得更好?請記住,我關心的是錯誤,而不是攻擊者。
$$ 1 $$ 也就是說,我創造它是為了學習。所以“只使用 UDP”或“只使用 TCP”確實適用,但這就是我不適用的原因。 $$ 2 $$ 如果是 16 位可能使用 MD5,如果是 48 位可能使用 SHA。
您可以使用 MD5 或 SHA-1 或 SHA-256 或 SHAKE128 的 16 位截斷作為校驗和,但這不是一個好的校驗和。
為什麼不?讓我們通過一個統一的隨機函式對它們進行建模 $ t $ 位,在這種情況下這是一個合理的模型。在這種情況下, $ \Pr[H(x) = h] = 1/2^t $ 對於任何消息 $ x $ 和雜湊 $ h $ ,並且每個 $ H(x) $ 對於每個不同的是獨立的 $ x $ . 因此,未能檢測到錯誤的機率 $ e $ 在一條消息中 $ x $ 是 $ \Pr[H(x + e) = H(x)] = 1/2^t $ 對於任何消息 $ x $ 和任何錯誤 $ e $ . 這是您希望從設計為隨機預言機(或接近它,儘管有長度擴展)的雜湊函式中獲得的最佳錯誤檢測。
如果您選擇好的 16 位 CRC(預印本、免付費牆;網站),那麼您可以得到保證:
- 只要生成多項式有,任何奇校驗錯誤都將被檢測到 $ x + 1 $ 作為一個因素;
- 任何高達 16 位的突發錯誤都將被檢測到,但生成多項式本身的錯誤除外,前提是生成多項式沒有 $ x $ 作為一個因子(即,具有非零常數項);
- 在達到一定大小的數據字中,將檢測到許多達到一定漢明權重的錯誤。
為隨機預言機使用而設計的加密雜湊函式,如 MD5、SHA-1、SHA-256、SHAKE128等,不保證這些。它們的計算成本通常也比校驗和之類的錯誤檢測程式碼高得多,因為您為抗碰撞付出了極高的成本,而這與錯誤檢測無關。
- 簡單地採用校驗和的“子字元串”會產生什麼後果?我可能天真地假設它只會增加碰撞的可能性。
碰撞在這裡無關緊要。唯一相關的是錯誤檢測的機率。MD5 或 SHA-1 或 SHA-256 或 SHAKE128 的任何子串都與其他任何子串一樣好。
- 是否有任何理由更喜歡使用最後x位而不是前x位,反之亦然?
不。如果這導致錯誤檢測的機率明顯不同,那麼這將是關於散列函式的一個值得注意的結果。
- 當像這樣截斷校驗和時,SHA 實際上是否比 MD5 執行得更好?請記住,我關心的是錯誤,而不是攻擊者。
不,它們都是檢測獨立隨機誤碼的錯誤選擇。