Internet 校驗和(Checksum)僅計算頭部的正確性,這一點很重要,這意味着 IP 協議不檢查 IPv4 packet 有效載荷部分的數據正確性。為了保證有效載荷部分的正常傳輸,其他協議必須通過自己的協議數據完整性檢測機制來保護重要數據。我們可以看到在封裝在 IP 的幾乎所有協議(UDP、TCP、ICMP、IGMP)在自己頭部中都有一個涵蓋頭部數據的校驗和。
IPv6 放棄了校驗和字段。原因如下:位錯誤帶來的后果一般是數據被投遞到錯誤的目的地、數據的來源顯示錯誤、有效載荷中的位錯誤。由於位錯誤比較少見,而且其他上層協議的字段提供了對有效載荷部分的更有力的確保正確性的機制,因此IPV6刪除了這個字段。
特別的,當 IPv4 的數據包經過一台路由器時,TTL 字段減一會導致頭部校驗和的重新計算,即每一跳路由都會導致校驗和的重新計算。
校驗和檢測失敗時 IPv4 將直接丟棄接收到有誤的數據包不會生成差錯信息,更高層需要以某種方式檢測丟失的數據報並在必要時重新傳輸。
internet校驗和的內容
Internet 校驗和的內容如下
- 將校驗和的字段設置為零。
- 將整個頭部(僅有 header 部分)認為是一個 16 bits integer 的一個序列。計算這一系列的 16 位整數的反碼和。將運算結果存放到校驗和字段內。
- 收到 IPv4 packet 時,對整個 header (校驗和字段不是 0 而是有填充)進行相同的計算。反碼和結果應該為 0 ,代表數據無誤。若非 0 ,則代表數據有誤
實例
例如要發送的 packet 內容是 :E3 4F 23 96 44 27 99 F3 【00 00】 (checksum 字段清零)
將整個序列看成 16 位的整數,一個十六進制數是 4 bits,所以要看成 4 個十六進制數為一個整數。
二進制反碼求和:從低位到高位逐列進行和計算,如果最高位(16位)進位,則得到的結果加1,一直循環到最高位沒有進位為止.最后把得到的結果取反.
可以用如下的簡單方法求反碼和:對幾個數進行補碼和,也就是我們通常所用的加法,然后將進位的數字加到最低位。
最后把結果取反。
- 補碼和:E34F + 2396 + 4427 + 99F3 = 1E4FF
- 反碼和:進位的數字加到最低位:E4FF + 1 = E500
- 取反:checksum = ~(E500) = 1AFF
則填充 checksum 之后發送的 packet 內容變成:E3 4F 23 96 44 27 99 F3 【1A FF】
接收方檢測過程:計算包括 checksum 在內的整個 packet 的反碼和,再取反。
- 補碼和:E34F + 2396 + 4427 + 99F3 + 1AFF = 1FFFE
- 反碼和:進位的數字加到最低位:FFFE + 1 = FFFF
- 取反結果 = ~(FFFF) = 0
若結果為 0 ,說明數據在傳輸過程中沒有發生變動。若結果不為 0 ,則數據在傳輸過程中有變動、受損。
數學性質
這里運用到離散數學中關於群論的知識點。
集合 G 不為空集,在 G 上的二元運算滿足封閉性、結合律、存在單位元、每個元素都有逆元,則稱<G, +> 為群,若滿足交換律,則稱群 G 為阿貝爾群。
可以通過觀察發現,16 位整數的一個十六進制值序列集合 V = {0001,0002,...,FFFF} ,定義 + 為二進制反碼和運算,<V, +> 構成阿貝爾群。
- 對於任意的 X,Y in V, (X + Y) in V [封閉]
- 對於任意的 X,Y,Z in V, X + (Y + Z) = (X + Y) + Z [可結合]
- 對於任意的 X in V, e + X = X + e = X ,e = FFFF [單位元 e 是 FFFF]
- 對於任意的 X in V, 存在 X′ in V 使 X + X′ = e [每個元素都存在逆元]
- 對於任意的 X,Y in V, (X + Y) = (Y + X) [交換律]
事實上,觀察構造 checksum 的過程我們可以得知:checksum 其實是前面 4 個 16 bit integer 做二進制反碼和運算(下文用 ‘+’ 代替)的結果的取反。取反這個操作特別的有意思,因為你對任何一段長度為 n 的二進制數據取反,與原來的數據相加,結果一定是長度為 n 的 1 串。
例如:1011,取反是 0100。1011 + 0100 = 1111
所以,對於 16 bit integer,這個結果一定是 FFFF。FFFF 在我們前面的分析中,就是阿貝爾群<V, +>的單位元!所以我們可以得出一個結論:在構造 packet checksum 時,checksum 其實就是其余數據在群<V, +>中的逆元!!
當收到 packet 的一方,在做驗證的時候,因為前面的 4 個 16 bit integer 和后面這 2 個字節的 checksum 是互為逆元的,所以對它們進行 + 的運算結果一定是單位元 FFFF。而由於整個運算集合構成了一個群,因此確保了每一個元素都有一個對應的逆元,也就證明了:如果檢驗和檢測正確,意味着數據完好,如果出錯,意味着數據受損。
關於這個十六位整數的十六進制值序列集合,非常讓人感興趣的一點是 其中沒有 0000。這是為什么呢?我們考慮一下,如果將數字0000放入集合,則 <V, +> 不再是一個阿貝爾群。
0000 顯然可以作為單位元 e。對於群,每個元素都要有一個逆元,取隨意的元素 AB12 來說,需要有一個逆元 X′ + AB12 = 0000,這樣的 X′ 在<V, +>是不存在的。因此,我們需要排除 0000 ,使得<V, +> 構成阿貝爾群。
那么排除 0000的道理又何在呢?首先,排除 0000 使得<V, +>是一個阿貝爾群,之前已經說過了。第二條理由是,任何一個合法的 IPv4 包,不可能所有的字節都為 0 。如果要將 0000 納入群眾,則是考慮存在一個合法的 IPv4 包,除了 checksum 之外的字節都為 0 的情況,而這種情況
- 會導致
<V, +>不再是一個阿貝爾群。 - 實際是不存在的,不存在任何一個合法的 IPv4 頭部全是 0 的情況。
因此我們可以排除 0000,由此推斷出 Internet 校驗和的群屬性。
參考鏈接:http://blog.csdn.net/qq_34369618/article/details/60603867
