用 16 位 CRC 實現 32 位驗證碼?
我正在編寫具有硬體 16 位 CRC 模組的嵌入式晶片。我必須保護一些數據字節 $ d_0,d_1,…,d_{n-1} $ 反對因突然失去權力而引起的腐敗;32 位 CRC 可以提供我需要的保護級別,但晶片沒有這種能力。
不幸的是,CRC 模組使用了一個無法更改的硬編碼多項式。而且我需要盡可能快的計算。也許基於表的 CRC 算法足夠快,但表會佔用 1 KB 的 ROM,如果可以的話,我想避免這種情況。
所以我的問題是:我能以某種方式使用這個硬體 CRC-16 模組來達到我需要的安全級別嗎?
我目前的想法是計算 $ CRC_{\mathrm{forward}} $ ,數據字節的CRC-16 $ d_0,d_1,…,d_{n-1} $ , 和 $ CRC_{\mathrm{backward}} $ ,數據字節的CRC-16 $ d_{n-1},d_{n-2},…,d_0 $ , 並簡單地連接這兩個 16 位 CRC 以創建一個 32 位 EDC。這足夠了嗎?或者這兩個CRC在某種意義上是依賴的?
更準確地說:假設 $ D $ 是數據,並且 $ E $ 是一個損壞的版本 $ E \ne D $ . 然後我想要機率 $ CRC_{\mathrm{forward}}(E) = CRC_{\mathrm{forward}}(D) $ 獨立於機率 $ CRC_{\mathrm{backward}}(E) = CRC_{\mathrm{backward}}(D) $ . 這是這種情況,還是我錯過了什麼?
**編輯添加:**如果差異 $ E \oplus D $ 是回文的,並且 $ CRC_{\mathrm{forward}}(E) = CRC_{\mathrm{forward}}(D) $ , 然後 $ CRC_{\mathrm{backward}}(E) = CRC_{\mathrm{backward}}(D) $ . 所以這個想法是行不通的。有人有更好的主意嗎?
CRC 基於不可約多項式,多項式的選擇由要檢測的錯誤類型驅動(例如,乙太網的 CRC 32 對於單比特和雙比特錯誤以及更多典型的雜訊傳輸類型的錯誤是“好”的) . 作為一般規則,所有 CRC 都可以很好地檢測達到一定數據量的單個位(乙太網 CRC 32 約為 11 Kbit)。
可以看出 CRC 對由您的數據 d0, d1 … dn 製成的大量數進行了模運算。如果您擔心碰撞(即來自不同數據集的相同模數)。你可以猜到一些殘留物,比如你的回文案,這讓你感覺很糟糕。但是您不必擔心,因為無論您做出何種選擇,您總是會得到相同數量的殘留碰撞,但是因為您無法輕易猜到它們,您會產生安全級別提高的錯誤印象。
當應用於隨機數據時,多項式 CRC 是所有散列方法中最公平的。
兩次使用您的 crc 時,您可以移動數據,它只會移動 crc 值。您可以旋轉輸入數據,它會旋轉 crc 值。您可以通過對常量進行異或來屏蔽輸入數據,它只會將 crc 與常量異或。您也可以鏡像數據,這將鏡像殘留物。如果在第一次 crc 計算中出現取消的錯誤,它們很可能會在第二次 crc 計算中取消。
這是一個加密論壇,也許您可以使用您的輸入數據作為 feistel 密碼的密鑰並使用固定常量作為輸入數據,例如參見 http://en.wikipedia.org/wiki/Feistel_cipher中的圖片,映射您的值 d0, d1 .. dn 到 K0,K1,Kn,並選擇 2 個常數作為 L0 和 R0,並添加 3 個終端輪。您的輸出值 LN 和 Rn 是您的數據的雜湊值。如果它是加密質量的,那麼它必須適合散列。
但是在所有情況下,您將 N 個輸入位映射到 C 個輸出位,衝突的風險是不變的。您唯一可以希望的是單個位錯誤在輸出位內有更好的擴散。
現在,您可能會期望在斷電後會出現某種類型的修改數據,或者您的數據不是“隨機的”,例如大量歸零位。在這種情況下,您可以考慮第二種不同的簡單算法。位奇偶校驗?簡單的字節總和?最簡單的一種是 adler32。眾所周知,增量更改是“壞”的(希望由多項式 CRC 覆蓋),但對零小數據是“好”的。這完全取決於您要保護的數據類型(例如具有小值的計數器)和您要檢測的錯誤類型(斷電後重置為 0xaa55)。