【问题标题】:Reproducable cryptographic hashes of Rust structs/enumsRust 结构/枚举的可重现加密哈希
【发布时间】:2020-07-21 07:20:39
【问题描述】:

目前我正在使用以下代码来获取 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 结构和枚举进行加密散列,以便无论架构/字长/字节序如何,散列都是相同的? (我在这些中不使用usize。)

【问题讨论】:

    标签: rust endianness sha256


    【解决方案1】:

    如果您想使用加密哈希对对象进行哈希处理,则必须将其转换为字节流,因为这是加密哈希唯一接受的内容。我们一般称这种序列化。

    你可以做一些事情:

    • 找到最快的通用序列化格式。 JSON 对此不利,因为它不能有效地序列化字节序列,因此您可以尝试 CBOR、Msgpack 或其他一些二进制格式。
    • 向您的代码添加测试,将常见结构散列到预期值,以便您可以验证它们是否按预期工作并避免意外破坏。
    • 如果可能,请在哈希中添加版本字段,以便在需要更改序列化程序或序列化的字节结构时调整版本。
    • 使用比 SHA-256 更快的哈希,例如 SHA-512、SHA-512/256 或 BLAKE2b(在 64 位系统上)或 BLAKE2s(在 32 位系统上)以降低整体操作的成本.

    或者,您可以尝试构建自定义的Hasher 实现,该实现也可以输出 SHA-256 值。然后,您的结构将需要实现Hash 而不是Serialize,并且您将逐步进行散列。这可能会也可能不会更快。

    【讨论】:

    • 用于 HashMap 的非加密哈希是否依赖于架构?如果不是,它们如何获取它们的字节序列,我可以以相同的方式获取它们吗?
    • 可能。您必须查看并查看默认实现散列是本机字节序还是固定字节序。
    • doc.rust-lang.org/src/core/hash/mod.rs.html#570-578 表明内置哈希(例如doc.rust-lang.org/std/hash/trait.Hash.html#impl-Hash-11 i32)没有考虑字节序。如果我认为值得,我可以复制、修改 Hash trait 的实现并将其粘贴到新的 EndianHash trait 中。
    猜你喜欢
    • 2023-01-03
    • 2015-01-12
    • 1970-01-01
    • 2013-04-10
    • 1970-01-01
    • 2016-02-29
    • 1970-01-01
    • 2011-01-18
    • 2011-05-02
    相关资源
    最近更新 更多