先确定校验覆盖哪些数据
校验过程需要确定算法、覆盖范围和校验字段本身怎样参与计算。发送端或存储端计算附加值,读取端按相同约定验证;数据不同而校验值相同的情况仍可能存在,这种碰撞取决于具体方法。
例如gzip使用未压缩内容的CRC-32,而Internet校验和采用16位反码加法;不能把一种方法计算的值交给另一种验证。校验覆盖内容之外的字段,也不会仅因数据主体通过检查就自动受到保护。
Internet校验和如何折回进位
RFC1071把相邻字节配成16位数并求反码和;产生最高位进位时,把进位加回低位。生成时先清零校验字段,对总和取反后写入;验证时把该字段也算进去,总和全为1表示通过。奇数字节输入按规则补零参与最后一组计算。
在保持字节奇偶位置约定的前提下,这种求和可以分组、重排或使用更宽的累加器再折回,便于实现加速。这个便利也意味着某些数据重排或抵消变化无法区分,不能把“算得快”理解为对所有错误都同样敏感。
参考:[1]
增量更新也要遵守完整算术
只改少数字段时,可以利用旧值和新值更新校验,而不重新扫描全部内容。反码算术有正零与负零两种表示,照搬普通代数变形可能在边界产生不同结果;RFC1624专门修正了旧增量公式的这一问题。
通过校验只排除了该方法能发现的不一致。主动攻击者可能连同数据一起更改校验值;需要确认发送者或抵抗伪造时,应使用带密钥认证等机制。校验和也不替代备份、重传或错误纠正,失败后如何恢复需要另外设计。