校验和是一种用于验证数据完整性的方法,通常包含普通校验和和复杂校验和。这里主要说明普通校验和。
- 普通校验和:简单,快速,如IPv4协议
- 复杂校验和:复杂,较慢,如文件验证
普通校验和
以16位为例:
计算校验和:首先计算每个数据的和,如果超过16位,取高16位与低16位相加,最后取反。
验证校验和:计算每个数据的和(包含之前计算的校验和),如果超过16位,取高16位与低16位相加,如果结果全为1,因为以16位为例,所以结果为 0xFFFF
时则说明数据传输没有出错。
实例代码:
ipt">// 计算校验和
function calculateChecksum(arr) {let sum = 0;for (let msg of arr) {sum += msgif (sum > 0xFFFF) {sum = (sum & 0xFFFF) + sum >> 16;}}return ~sum & 0xFFFF;
}
ipt">// 验证校验和
function verifyChecksum(arr) {let sum = 0;for (let msg of arr) {sum += msgif (sum > 0xFFFF) {sum = (sum & 0xFFFF) + sum >> 16;}}return sum === 0xFFFF;
}
注意⚠️:验证的时候是包含你之前计算得出的校验和。
复杂校验和
复杂校验和可以防止数据被篡改,如MD5,SHA-1等。
拓展
这里额外说明一下 IPv4 的校验和,当然校验和不仅限于用于 IPv4,你也可以尝试用于其他方面。
IPv4 协议头部包含 TTL 属性,它代表一个8位的生命周期,通常为 32 或 64,每经过一个路由器时,该值都会减1,如果为 0 时,该数据报就会被丢弃。
IPv4 的校验和计算方法是将头部一系列16位数字相加,然后使用简单校验和得出,但头部中包含了TTL属性,因此每次TTL减1都要重新计算校验和。
这里有一个快速的计算方法:
ipt">newChecksum = oldChecksum + (oldTTL - newTTL)
- oldChecksum:旧的校验和
- oldTTL:旧的TTL
- newTTL:新的TTL
这样就不需要每次重新将头部一系列16位数字相加。
详细可以参考:RFC 1624