Rust 的可重现加密哈希 structs/enums
Reproducable cryptographic hashes of Rust structs/enums
目前我正在使用以下代码获取 Rust 结构和枚举的 sha256 哈希值。
pub fn sha256<T: Sized + Serialize>(ser: T) -> [u8; 32] {
let str = ron::ser::to_string(&ser).expect("serialization has failed");
let mut hasher = Sha256::new();
hasher.update(str);
let hash = hasher.finalize();
*hash.as_ref()
}
这可行,但远非理想:
- 如果 RON 序列化发生变化,哈希值也会发生变化。
- 序列化正在浪费 CPU 个周期。
许多类型都有 .hash()
方法,但这似乎适用于 64 位非加密哈希(HashMap 等)。
我如何加密散列任意 Rust 结构和枚举,这样散列将是相同的,而不管 architecture/word-size/endianess? (我不在其中使用 usize
。)
如果你想用加密散列来散列一个对象,你必须把它变成一个字节流,因为这是加密散列唯一接受的东西。我们一般会称之为序列化。
您可以做一些事情:
- 找到最快的通用序列化格式。 JSON 对此不利,因为它不能有效地序列化字节序列,因此您可以尝试 CBOR、Msgpack 或其他一些二进制格式。
- 将常见结构散列到预期值的代码添加测试,以便您可以验证它们是否按预期工作并避免意外中断。
- 如果可能,将版本字段添加到您的散列中,以便在需要更改序列化程序或序列化的字节结构时可以更改版本。
- 使用比 SHA-256 更快的散列,例如 SHA-512,SHA-512/256,或 BLAKE2b(在 64 位系统上)或 BLAKE2s(在 32 位系统上)以降低成本整体运行。
或者,您可以尝试构建自定义 Hasher
实现,它也可以输出 SHA-256 值。然后您的结构将需要实现 Hash
而不是 Serialize
并且您将逐步进行散列。这可能会或可能不会更快。
目前我正在使用以下代码获取 Rust 结构和枚举的 sha256 哈希值。
pub fn sha256<T: Sized + Serialize>(ser: T) -> [u8; 32] {
let str = ron::ser::to_string(&ser).expect("serialization has failed");
let mut hasher = Sha256::new();
hasher.update(str);
let hash = hasher.finalize();
*hash.as_ref()
}
这可行,但远非理想:
- 如果 RON 序列化发生变化,哈希值也会发生变化。
- 序列化正在浪费 CPU 个周期。
许多类型都有 .hash()
方法,但这似乎适用于 64 位非加密哈希(HashMap 等)。
我如何加密散列任意 Rust 结构和枚举,这样散列将是相同的,而不管 architecture/word-size/endianess? (我不在其中使用 usize
。)
如果你想用加密散列来散列一个对象,你必须把它变成一个字节流,因为这是加密散列唯一接受的东西。我们一般会称之为序列化。
您可以做一些事情:
- 找到最快的通用序列化格式。 JSON 对此不利,因为它不能有效地序列化字节序列,因此您可以尝试 CBOR、Msgpack 或其他一些二进制格式。
- 将常见结构散列到预期值的代码添加测试,以便您可以验证它们是否按预期工作并避免意外中断。
- 如果可能,将版本字段添加到您的散列中,以便在需要更改序列化程序或序列化的字节结构时可以更改版本。
- 使用比 SHA-256 更快的散列,例如 SHA-512,SHA-512/256,或 BLAKE2b(在 64 位系统上)或 BLAKE2s(在 32 位系统上)以降低成本整体运行。
或者,您可以尝试构建自定义 Hasher
实现,它也可以输出 SHA-256 值。然后您的结构将需要实现 Hash
而不是 Serialize
并且您将逐步进行散列。这可能会或可能不会更快。