灯笼海棠

Merkle Trees 可在 Fuchsia 生态系统中的多个位置使用,包括 FAR 归档格式、Blob 存储文件系统和 Package Manager

Zircon 中,zx-verity 为应用组件提供了一个 API,以便其从本地存储空间读取数据。在检索数据时,系统会验证数据的完整性,如果数据被修改或损坏,则会导致读取失败。zx-verity 基于 Merkle 树,并且源自 Chrome 操作系统中的类似系统。

所有这些实现均采用本文中所述的算法。

Merkle 树的参数

  • 块大小:8kb,填充值 0。
  • 根摘要大小:32 个字节。
  • 哈希算法:SHA-256。
  • 块摘要计算:SHA-256(u64(offset | level) + u32(长度)+ 数据)

定义

Merkle 树包含层次。级别是树中的一行,从 0 开始,向上计数。级别 0 表示包含输入流区块哈希的级别。

每个级别都包含前一个级别的多个哈希。一个级别的哈希根据前一级别的 8kb 块(或者,如果级别为 0,则为数据)计算得出,前加一个块标识。

块标识是块当前级别和当前级别索引的起始字节索引的二进制“或”运算,后跟块的长度。对于级别 0,块的长度为 8kb,最后一个块除外,它可能小于 8kb。所有其他层使用 8kb 的长度,即使最后一个块填充了 0 也是如此。

计算等级

  1. 使用索引、从 0 开始的偏移量以及一个空的哈希列表来初始化层级。
  2. 对于每 8kb(或剩余部分)输入,计算下一个块标识:先获取级别索引与当前偏移量的二进制 OR,然后得出输入的长度。
  3. 初始化 SHA-256 摘要,向其附加标识和输入,如果输入短于 8kb,则填充从 0 到 8kb 的填充。
  4. 将摘要的输出附加到相应级别的哈希列表。按输入长度增加偏移量。
  5. 重复 1-4,直到用完所有输入。
  6. 如果哈希长度为 32,则完成。
  7. 如果哈希的长度未 8kb 对齐,则 0 会填充到 8kb 对齐,并计算更多级别,直到存在包含单个 32 字节摘要的根级别。

计算根摘要

使用输入数据计算级别 0。使用上一级哈希作为输入数据来构建和计算后续层级,直到一级哈希正好包含 32 个字节。最后的这一级别包含 Merkle 树的根摘要。

关于空摘要的说明

一种特殊情况是,在没有输入数据时,实现可能需要独立处理计算。空输入的摘要就是 12 0 字节的 SHA-256,单个长度为 0 的块的块标识。

示例值

  • 空摘要: 15ec7bf0b50732b49f8228e07d24365338f9e3ab994b00af08e5a3bffe55fd8b
  • 8192 个字节 0xff - "oneblock" 68d131bc271f9c192d4f6dcd8fe61bef90004856da19d0f2f514a7f4098b0737
  • 65536 字节 0xff -“small”f75f59a944d2433bc6830ec243bfefa457704d2aed12f30539cd4f18bf1d62cf
  • 2105344 个字节的 0xff -“大”7d75dfb18bfd48e03b5be4e8e9aeea2f89880cb81c1551df855e0d0a0cc59a67
  • 2109440 个字节的 0xff -“未对齐”7577266aa98ce587922fdc668c186e27f3c742fb1b732737153b70ae46973e43
  • 0xff0080 个字节填充了重复的 0xff0080 -“紫红色” 2feb488cffc976061998ac90ce7292241dfa86883c0edc279433b5c4370d0f30