SipHash 1.2.2

SipHash 1.2.2

测试已测试
语言语言 SwiftSwift
许可 MIT
发布最后发布2018年6月
SPM支持 SPM

Károly LőrenteyThe Attaswift 项目Koray Koska 维护。



SipHash 1.2.2

SipHash

Swift 4.0 License Platform

Build Status Code Coverage

Carthage compatible CocoaPod Version

SipHash 是由 Jean-Philippe Aumasson 和 Daniel J. Bernstein 在 2012 年设计的 SipHash 哈希算法的纯 Swift 实现

SipHash 是一族针对短消息优化速度的伪随机函数(又称键控哈希函数)。

目标应用包括网络流量身份验证和对抗哈希洪水 DoS 攻击。

SipHash 实际上安全、快速且简单

  • SipHash 比前一代加密算法(例如基于通用哈希的 MAC)更简单、更快
  • SipHash 在性能上可以与非加密算法(例如 MurmurHash)相媲美

-- 131002.net

SipHash 有多种版本;此包实现了被称为 SipHash-2-4 的版本。

请注意,Swift 标准库 已经包含了 SipHash-2-4 和 SipHash-1-3 的实现;然而,API 当前是私有的,且在 stdlib 之外不可用。此包提供了一个可用于第三方代码的独立实现。

SipHash 的当前版本需要 Swift 4。

示例代码

import SipHash

// `SipHashable` is like `Hashable`, but simpler.
struct Book: SipHashable {
    let title: String
    let pageCount: Int

    // You need to implement this method instead of `hashValue`.
    func appendHashes(to hasher: inout SipHasher) {
         // Simply append the fields you want to include in the hash.
         hasher.append(title)
         hasher.append(pageCount)
    }

    static func ==(left: Book, right: Book) -> Bool {
         return left.title == right.title && left.pageCount == right.pageCount
    }
}

// You can now use Books in sets or as dictionary keys.
let book = Book(title: "The Colour of Magic", pageCount: 206)
let books: Set<Book> = [book]


// If you prefer to do so, you may also create & use hashers directly.
var hasher = SipHasher()
hasher.add(book)
hasher.add(42)
// Finalizing the hasher extracts the hash value and invalidates it.
let hash = hasher.finalize()

我会为什么要使用 SipHash?

实现一个良好的hashValue功能是一项挑战,即使我们只需要组合几个字段的值。我们需要设计一个确定的函数,将这些字段的值完美融合,并生成一个固定宽度的结果,同时在典型输入上碰撞很少。但是,有多少碰撞才算“太多”?我们甚至知道我们的“典型输入”是什么样的吗?对我来说,这两个问题的答案通常都是“我一点都不知道”,我相信你也有同样的问题。

因此,验证我们的hashValue实现是否良好是一项令人沮丧的任务。

我们需要查看不同输入下哈希函数的行为来检查哈希函数的性质。虽然很容易编写测试来验证相同值的hashValues相等,但要验证哈希值很少发生碰撞就需要对“典型”输入的统计特性做出某些假设——即使我们对此有足够的信心,编写代码来实现也是非常复杂的。

为什么不使用专门设计用于将数据混合成哈希值的算法呢?使用标准化的算法意味着我们不再需要担心碰撞行为:如果算法设计得好,我们将始终得到良好的结果。

SipHash算法是哈希的一个特别好的选择。它实现了一个从128位密钥(通常在每次程序的执行中随机生成)初始化的256位内部状态的64位加密消息认证码(MAC)。SipHash旨在防御哈希碰撞攻击,同时使用简单且快速。它已经被Perl、Python、Ruby、Rust甚至Swift自身使用——这就是为什么Hashable的文档明确警告,hashValue的值在执行之间可能会有所不同。

标准库已经实现了SipHash,但该实现是私有的。(技术上可供使用,但不是stdlib API的正式部分,并且即使在一些点版本发布中也会发生变化/删除。)我预计stdlib的SipHash重构版本将在未来的Swift版本中作为公共API提供。但在我们等待这个版本时,这个包提供了一个今天即可使用的替代实现。

这段代码满是错误吗?

当然。请报告你发现的所有错误!

该包有100%的单元测试覆盖率。不幸的是,这并不能告诉你它在实际应用中的可靠性多少。

测试套件验证包生成的值与SipHash原始作者提供的测试向量匹配,这使我合理地相信这个包正确实现了SipHash。当然,结果可能会有所不同。

参考文档

Jazzy提供,《格式优雅的参考文档可供使用。

安装

CocoaPods

如果你使用CocoaPods,可以在你的Podfile中将其作为依赖项开始使用SipHash

pod 'SipHash', '~> 1.2'

Carthage

对于Carthage,将以下行添加到你的Cartfile中。

github "attaswift/SipHash" ~> 1.2

Swift包管理器

对于Swift Package Manager,将SipHash添加到你的Package.swift文件中的依赖项列表中。

import PackageDescription

let package = Package(
    name: "MyPackage",
    dependencies: [
        .Package(url: "https://github.com/attaswift/SipHash.git", from: "1.2.1")
    ]
)

独立开发

如果你不使用依赖管理器,需要将此仓库克隆到项目附近的位置,并将SipHash.xcodeproj的引用添加到项目的xcworkspace中。你可以将SipHash的克隆版本放在磁盘上的任何位置,但将其设置为应用程序顶层Git仓库的子模块是个好主意。

要将您的应用程序的二进制文件与SipHash连接起来,只需将 SipHash 项目的 SipHash.framework 添加到 Xcode 中应用程序目标“通用”页面上的“嵌入的二进制文件”部分。只要您的工作区中引用了 SipHash 项目文件,当您点击“嵌入的二进制文件”列表中的“+”按钮时,此框架就会在“选择要添加的项目”表单中列出。

除将框架目标添加到嵌入二进制文件之外,无需进行任何其他设置。