CRC 是根据输入计算的一组位。
如果您的输入与 CRC 大小相同(或更小)(在您的情况下 - 32 位),您可以找到创建此 CRC 的输入 - 实际上是反转它。
如果您的输入大于 32 位,但您知道除 32 位之外的所有输入,您仍然可以反转 CRC 以找到丢失的位。
但是,如果输入的未知部分大于 32 位,则无法找到它,因为存在不止一种解决方案。
我为什么要告诉你这个?想象一下你有集合的 CRC
{A,B,C}
假设您知道B 是什么,您现在可以轻松计算集合的CRC
{A,C}
(我的意思是“轻松” - 无需遍历整个 A 和 C 输入 - 如您所愿)
现在您有 64 位描述 A 和 C!而且由于我们不必遍历A 和C 的全部内容来做到这一点——这意味着即使我们缺少关于A 和C 的信息,我们也可以做到这一点。
所以看起来如果存在这样的方法,如果我们有它的 CRC,我们可以神奇地从输入中修复超过 32 个未知位。
这显然是错误的。这是否意味着没有办法做你想做的事?当然不是。但它确实限制了我们如何做到这一点:
选项 1:我们无法从 CRC({A,C}) 获得更多我们在 CRC({A,B,C}) 中没有的信息。这意味着A 和C 对CRC 的(相对)影响不会随着B 的移除而改变。基本上 - 这意味着在计算 CRC 时,我们在添加新元素时使用了一些“顺序不重要”的函数:
例如,我们可以使用CRC({A,B,C}) = CRC(A) ^ CRC(B) ^ CRC(C)(不是很好,好像 A 出现两次它是相同的 CRC,就好像它从未出现过一样),或 CRC({A,B,C}) = CRC(A) + CRC(B) + CRC(C) 或 CRC({A,B,C}) = CRC(A) * CRC(B) * CRC(C)(确保 CRC(X)很奇怪,所以它实际上只是 31 位 CRC)或CRC({A,B,C}) = g^CRC(A) * g^CRC(B) * g^CRC(C)(其中^ 是电源 - 如果您想要加密安全,则很有用)等等。
选项 2: 我们确实需要所有 A 和 C 来计算 CRC({A,C}),但是我们有一个数据结构,如果我们这样做的话,它会在时间上变得不是线性的已经计算好了CRC({A,B,C})。
如果您特别想要 CRC32,并且不介意在计算后记住除 CRC 之外的更多信息(CRC 仍然是 32 位,但您记得数据结构为 O(len(A,B ,C)),您稍后将使用它来更有效地计算 CRC{A,C})
这将如何运作?许多 CRC 只是在输入上应用多项式。
基本上,如果您将输入划分为 n 每个 32 位的块 - X_1...X_n - 有一个矩阵 M 这样
CRC(X_1...X_n) = M^n * X_1 + ... + M^1 * X_n
(这里^是力量)
这有什么帮助?这个总和可以用树状方式计算:
CRC(X_1...X_n) = M^(n/2) * CRC(X_1...X_n/2) + CRC(X_(n/2+1)...X_n)
因此,您从树的叶子上的所有 X_i 开始,首先计算每个连续对的 CRC,然后将它们成对组合,直到获得所有输入的组合 CRC。
如果您记得节点上的所有部分 CRC,则只需执行 O(log(n)) 计算即可轻松删除(或添加)列表中任何位置的项目!
所以-据我所知,这是您的两个选择。我希望这不会太混乱:)
我个人会选择选项 1,因为它更简单……但生成的 CRC 不是标准的,而且不太……好。不像“CRC”。
干杯!