15 个版本 (破坏性更新)
0.12.1 | 2022年7月14日 |
---|---|
0.12.0 | 2021年9月16日 |
0.11.0 | 2021年7月17日 |
0.10.1 | 2020年2月27日 |
0.1.0 | 2017年10月18日 |
#315 在 密码学 分类中
每月下载量 254 次
在 9 个 包(6 个直接)中使用
115KB
1.5K SLoC
Bao 是 BLAKE3 验证流式传输的实现,如 BLAKE3 规范 第 6.4 节所述。像 BLAKE3 这样的树哈希使您能够在不重新哈希整个文件的情况下验证文件的一部分,使用一种编码格式,该格式将文件的字节与其哈希树的所有节点一起存储。客户端可以流式传输此编码,或者随机查找它,同时验证他们所读取的每个字节都与根哈希匹配。关于其工作原理的详细信息,请参阅 Bao 规范。
此项目包括两个 Rust 包,bao
库包和 bao_bin
二进制包。后者提供了 bao
命令行实用程序。
注意! Bao 是一种 beta 版本的加密软件。它尚未经过正式审计。
编码和解码
用例:一个安全消息应用可能通过在消息元数据中包含附件的哈希值来支持附件文件。使用序列哈希,接收者需要下载整个附件来验证它,但对于大型视频文件等来说这可能不太实际。使用 BLAKE3 和 Bao,接收者可以在接收视频附件的同时验证每个字节的完整性。(这个场景是 Bao 项目的原始动机。)
# Create an input file that's a megabyte of random data.
> head -c 1000000 /dev/urandom > f
# Convert it into a Bao encoded file.
> bao encode f f.bao
# Compare the size of the two files. The encoding overhead is small.
> stat -c "%n %s" f f.bao | column -t
f 1000000
f.bao 1062472
# Compute the BLAKE3 hash of the original file. The `b3sum` tool would
# also work here.
> hash=`bao hash f`
# Stream decoded bytes from the encoded file, using the hash above.
> bao decode $hash < f.bao > f2
> cmp f f2
# Observe that using the wrong hash to decode results in an error. This
# is also what will happen if we use the right hash but corrupt some
# bytes in the encoded file.
> bad_hash="0000000000000000000000000000000000000000000000000000000000000000"
> bao decode $bad_hash < f.bao
Error: Custom { kind: InvalidData, error: StringError("hash mismatch") }
验证切片
编码文件支持随机搜索,但在网络上搜索可能不可用或效率不高。(注意,在内容中进行一次搜索通常需要编码中的几次搜索,因为解码器逐级遍历哈希树。)在这些情况下,而不是尝试远程搜索,客户端可以请求包含所需内容字节的编码切片。创建切片需要发送者遍历整个编码,但接收者可以流式传输切片而无需进行任何搜索。解码切片使用与常规解码相同的根哈希,因此不需要发送者或接收者预先准备。
用例:一个类似 BitTorrent 的应用程序可以从不同的对等方获取文件的不同切片,而无需预先定义切片。或者,一个分布式文件存储应用程序可以请求从其存储提供商那里获取归档文件的随机切片,以证明它们诚实地存储了文件,而无需为未来的挑战准备或存储。
# Using the encoded file from above, extract a 100 KB slice from
# somewhere in the middle. We'll use start=500000 (500 KB) and
# count=100000 (100 KB).
> bao slice 500000 100000 f.bao f.slice
# Look at the size of the slice. It contains the 100 KB of content plus
# some overhead. Again, the overhead is small.
> stat -c "%n %s" f.slice
f.slice 107272
# Using the same parameters we used to create the slice, plus the same
# hash we got above from the full encoding, decode the slice.
> bao decode-slice $hash 500000 100000 < f.slice > f.slice.out
# Confirm that the decoded output matches the corresponding section from
# the input file. (Note that `tail` numbers bytes starting with 1.)
> tail --bytes=+500001 f | head -c 100000 > expected.out
> cmp f.slice.out expected.out
# Now try decoding the slice with the wrong hash. Again, this will fail,
# as it would if we corrupted some bytes in the slice.
> bao decode-slice $bad_hash 500000 100000 < f.slice
Error: Custom { kind: InvalidData, error: StringError("hash mismatch") }
外部模式
默认情况下,上述所有操作都与“组合”编码文件一起工作,即包含内容字节和树哈希字节交错在一起的文件。但是,有时您希望将它们分开,例如,为了避免复制一个非常大的输入文件。在这些情况下,您可以通过使用“外部”编码格式通过 --outboard
标志来实现。
# Re-encode the input file from above in the outboard mode.
> bao encode f --outboard f.obao
# Compare the size of all these files. The size of the outboard file is
# equal to the overhead of the original combined file.
> stat -c "%n %s" f f.bao f.obao | column -t
f 1000000
f.bao 1062472
f.obao 62472
# Decode the whole file in outboard mode. Note that both the original
# input file and the outboard encoding are passed in as arguments.
> bao decode $hash f --outboard f.obao f4
> cmp f f4
安装和从源代码构建
命令行工具 bao
作为 crates.io 上的 bao_bin
库发布。要安装它,将 ~/.cargo/bin
添加到您的 PATH
,然后运行
cargo install bao_bin
直接从本仓库构建二进制文件
git clone https://github.com/oconnor663/bao
cd bao/bao_bin
cargo build --release
./target/release/bao --help
tests/bao.py
是一个完全功能的 Python 实现,设计得尽可能短小和可读。它是理解涉及算法的良好起点,在深入研究 Rust 代码之前。
依赖关系
~1.5MB
~39K SLoC