【问题标题】:How to natively hash a struct without randomization?如何在没有随机化的情况下本地散列结构?
【发布时间】:2020-11-18 17:34:18
【问题描述】:

在 Swift 中是否可以在没有随机化的情况下对结构进行哈希处理?

struct Kiwi: Hashable {
    let userId: String
    let selections: Set<Int>
    
    init(userId: String, selections: Set<Int>) {
        self.userId = userId
        self.selections = selections
    }

    func hash(into hasher: inout Hasher) {
        hasher.combine(userId)
        hasher.combine(selections)
    }
}

let k1 = Kiwi(userId: "u1", selections: [1])
print(k1.hashValue)

let k2 = Kiwi(userId: "u1", selections: [1])
print(k2.hashValue)

不保证这些哈希值在不同的执行点上是相等的(由于哈希函数的随机化)。此哈希的目的只是生成结构值的签名,以便在结构的值相同时它们始终相同,无论何时执行。

目前,我已经创建了结构 Equatable 并仅比较结构实例,但更希望能够比较“签名”(即哈希)。

【问题讨论】:

    标签: swift hashable


    【解决方案1】:

    您应该制定自己的协议,例如:

    protocol Signable {
        /// A signature that's stable across app launches
        var signature: Signature { get }
    }
    

    Equatable/Hashable 是具有非常特定语义的标准协议(平等意味着可替代性,而 Hashability 是一种启发式,作为Equatable 的性能优化)。对于任何类似于相等检查或散列的东西,它们并不是包罗万象的语法包。

    另外请注意:Hasherrandomly seeded behavior故意的。它可以保护您免受hash-flooding DoS attacks 的侵害。你应该非常小心地规避这一点,因为你会将自己暴露在这个向量中。

    使用signature 来比较应用程序启动时持续存在的实例似乎很好。但我建议使用它来实现任何类型的散列数据结构,这些数据结构可能会受到攻击而退化为线性时间查找。

    【讨论】:

    • Signable 协议是一个有吸引力的解决方案。关于如何生成签名本身的任何高级建议?
    • @acidgate Swift 的Hasher 是具体类型,而不是协议。所以不幸的是,你不能只做一个新的实现。但是,您可以制作自己的单独哈希结构。 Swift 的 Hasher 使用 SipHash。它是开源的,因此您可以使用它作为参考:github.com/apple/swift/blob/main/stdlib/public/core/… SPM 现有的许多包都实现了 SipHash 或许多其他哈希。请记住,哈希函数有不同的应用,有不同的权衡。例如。速度慢且加密安全,而数据结构速度快且“足够好”。
    猜你喜欢
    • 2021-11-23
    • 2015-12-22
    • 1970-01-01
    • 1970-01-01
    • 2021-04-09
    • 2016-12-29
    • 1970-01-01
    • 2011-05-13
    • 1970-01-01
    相关资源
    最近更新 更多