如何在没有随机化的情况下本地散列结构?

How to natively hash a struct without randomization?

在 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 并且只比较结构实例,但更愿意能够比较“签名”(即哈希)。

你应该制定自己的协议,比如:

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

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

还要注意:randomly seeded behavior of Hasher is intentional. It protects you against hash-flooding DoS attacks。你应该非常小心地避免这种情况,因为你会将自己暴露在这个向量中。

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