为什么 LevelDB 和 RocksDB 需要“屏蔽 CRC32”

Myr*_*rfy 5 crc32 crc leveldb rocksdb

crc32.hleveldb或rocksdb的注释中,我们可以找到这样的注释:

static const uint32_t kMaskDelta = 0xa282ead8ul;

// Return a masked representation of crc.
//
// Motivation: it is problematic to compute the CRC of a string that
// contains embedded CRCs.  Therefore we recommend that CRCs stored
// somewhere (e.g., in files) should be masked before being stored.
inline uint32_t Mask(uint32_t crc) {
  // Rotate right by 15 bits and add a constant.
  return ((crc >> 15) | (crc << 17)) + kMaskDelta;
}
Run Code Online (Sandbox Code Playgroud)

那么,这意味着什么呢?为什么我们需要口罩?

rcg*_*ldr 0

面具

“掩码”在注释和一行代码中进行了解释。它通过右移 15 位并添加一个常数来修改 32 位 CRC。

为什么我们需要口罩?

掩码不是“需要的”,但建议在存储 CRC 时使 CRC 比标准 CRC 更复杂一些。我不知道为什么建议以这种方式“保护”存储的 CRC。如果“屏蔽”过程是固定且已知的,那么我看不出它如何帮助“保护”存储的 CRC。我认为这个面具是定制的,其他人不知道其实际使用情况。

计算包含嵌入 CRC 的字符串的 CRC 是有问题的

我不清楚这个评论的意思是什么。生成可以位于字符串中任何位置的数据以便计算出的 CRC 有效并不困难。通常,CRC 会附加到消息中,但可以通过将 CRC 乘以 (1/(2^(n)))(在适当的 Galois 字段中)(使用无进位乘法)向后循环 n 位,这可以加速使用 X86 的 pclmulqdq 等指令(它使用 xmm 寄存器)。例如,假设一个 32 位 CRC 将存储在m位字符串的位索引j处,包括数据和 CRC。索引j处的 32 位被清零,然后使用标准 CRC 来计算 CRC,就好像它将附加在位索引m处一样。然后 CRC 向后循环m - j位并存储在位索引j处。

在字符串中嵌入多个 CRC 将使逆向工程变得困难,但我见过用于游戏的保存文件有两个 CRC 的情况,两者都嵌入,并且黑客能够对双 CRC 方法进行逆向工程。