【发布时间】:2016-05-29 13:17:30
【问题描述】:
假设您有一个由 N 个 64 字节元素组成的数组计算得出的 MD5 和。我想用新元素替换源数组中任意索引处的元素。然后,我不想通过 MD5 函数重新运行它来重新计算 MD5 总和,而是想从结果中“减去”旧元素并将新数据“添加”到其中。
为了更清楚一点,这里有一些伪 Scala:
class Block {
var summary: MD5Result
// The key reason behind this question is that the elements might not be
// loaded. With a large array, it can get expensive to load everything just to
// update a single thing.
var data: Array[Option[Element]]
def replaceElement(block: Block, index: Integer, newElement: Element) = {
// we can know the element that we're replacing
val oldElement = block.data(index) match {
case Some(x) => x
case None => loadData(index) // <- this is expensive
}
// update the MD5 using this magic function
summary = replaceMD5(summary, index, oldElement, newElement)
}
}
replaceMD5 可以实现吗?虽然所有迹象都表明“这正在破坏(弱)加密哈希”,但实际的 MD5 算法似乎支持这样做(但我可能遗漏了一些明显的东西)。
【问题讨论】:
-
TTBOMK MD5 计算严格按递增顺序处理字节。如果是这样,您可以在每个 64 字节单元之后记录 MD5 计算的中间(状态)值序列:然后如果 data[i] 发生更改,您可以从这一点重新开始 MD5 计算,即仅重新计算剩余的 ( n-i+1)*64 字节。如果变化是均匀随机的,这将平均节省一半的计算量。 TTBOMK 任何更改都会以不可预知的方式改变所有“下游”状态,因此我怀疑是否可以采取任何措施来缓解即将开始的更改。
-
我相信如果不花更多时间然后重新运行 md5,这是不可能的。您能否说明为什么您认为实际的 MD5 算法似乎支持这样做?
-
问题不在于重新运行算法的计算时间——而是我必须执行昂贵的操作 (IO) 来确定哪些数据甚至可以提供给算法。
-
@SalvadorDali:显然 MD5 在设计时并没有考虑到这种疯狂的操作。我没有明确的理由相信这是可能的,但它似乎应该是,如果它的计算成本很高的话。如果不可能,那就这样吧。