Simple and secure hashing in Swift with the SipHash algorithm

Related tags

Security SipHash
Overview

SipHash

Swift 4.0 License Platform

Build Status Code Coverage

Carthage compatible CocoaPod Version

⚠️ WARNING
This package has been obsoleted by the Hasher type and the Hashable.hash(into:) requirement introduced in Swift 4.2. Using this package in not recommended in modern Swift code; instead, simply implement the standard Hashable. (The standard library changes introduced in SE-0206 are sort of like a version 2 of this package.)

SipHash is a pure Swift implementation of the SipHash hashing algorithm designed by Jean-Philippe Aumasson and Daniel J. Bernstein in 2012:

SipHash is a family of pseudorandom functions (a.k.a. keyed hash functions) optimized for speed on short messages.

Target applications include network traffic authentication and defense against hash-flooding DoS attacks.

SipHash is secure, fast, and simple (for real):

  • SipHash is simpler and faster than previous cryptographic algorithms (e.g. MACs based on universal hashing)
  • SipHash is competitive in performance with insecure non-cryptographic algorithms (e.g. MurmurHash)

-- 131002.net

SipHash has a variety of flavors; this package implements the one called SipHash-2-4.

Note that the Swift Standard Library already includes an implementation of SipHash-2-4 and SipHash-1-3; however, the APIs are currently private and not available for use outside of stdlib. This package provides an independent implementation that's available for use in third-party code.

The current release of SipHash requires Swift 4.

Sample Code

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()

Why Would I Use SipHash?

Unless you're targeting an ancient Swift release (<4.2), you shouldn't use SipHash. This package is obsolete; it remains here for posterity and for compatibility only. Do not import it into new code.

What follows is the original documentation, contrasting SipHashable to the original (now deprecated) Hashable.hashValue protocol requirement.

Repeated for emphasis: Do not import this package into newly written code.


Writing a good implementation of hashValue is hard, even if we just need to combine the values of a couple of fields. We need to come up with a deterministic function that blends the field values well, producing a fixed-width result without too many collisions on typical inputs. But how many collisions are "too many"? Do we even know what our "typical inputs" look like? For me, the answer to both of these questions is usually "I have absolutely no idea", and I bet you have the same problem.

Thus, verifying that our hashValue implementations work well is an exercise in frustration.

We need to somehow check the properties of the hash function by looking at its behavior given various inputs. It is easy enough to write tests for the requirement that equal values have equal hashValues. But verifying that the hash has few collisions requires making some assumptions on the statistical properties of "typical" inputs -- and even if we'd be somehow confident enough to do that, writing the code to do it is way too complicated.

Instead of rolling your own ad-hoc hash function, why not just use an algorithm designed specifically to blend data into a hash? Using a standardized algorithm means we don't need to worry about collision behavior any more: if the algorithm was designed well, we'll always have good results.

The SipHash algorithm is a particularly good choice for hashing. It implements a 64-bit cryptographic message-authentication code (MAC) with a 256-bit internal state initialized from a 128-bit secret key that's (typically) randomly generated for each execution of the binary. SipHash is designed to protect against hash collision attacks, while remaining simple to use and fast. It is already used by Perl, Python, Ruby, Rust, and even Swift itself -- which is why the documentation of Hashable explicitly warns that the value returned by hashValue may be different across executions.

The standard library already implements SipHash, but the implementation is private. (It is technically available for use, but it is not formally part of the stdlib API, and it is subject to change/removal across even point releases.) I expect a refactored version of stdlib's SipHash will become available as public API in a future Swift release. But while we're waiting for that, this package provides an alternative implementation that is available today.

Is this code full of bugs?

Indubitably. Please report all bugs you find!

The package has 100% unit test coverage. Unfortunately this doesn't tell you much about its reliability in practice.

The test suite verifies that the package generates values that match the test vectors supplied by SipHash's original authors, which makes me reasonably confident that this package implements SipHash correctly. Obviously, your mileage may vary.

Reference docs

Nicely formatted reference docs are available courtesy of Jazzy.

Installation

CocoaPods

If you use CocoaPods, you can start using SipHash by including it as a dependency in your Podfile:

pod 'SipHash', '~> 1.2'

Carthage

For Carthage, add the following line to your Cartfile:

github "attaswift/SipHash" ~> 1.2

Swift Package Manager

For Swift Package Manager, add SipHash to the dependencies list inside your Package.swift file:

import PackageDescription

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

Standalone Development

If you don't use a dependency manager, you need to clone this repo somewhere near your project, and add a reference to SipHash.xcodeproj to your project's xcworkspace. You can put the clone of SipHash wherever you like on disk, but it is a good idea to set it up as a submodule of your app's top-level Git repository.

To link your application binary with SipHash, just add SipHash.framework from the SipHash project to the Embedded Binaries section of your app target's General page in Xcode. As long as the SipHash project file is referenced in your workspace, this framework will be listed in the "Choose items to add" sheet that opens when you click on the "+" button of your target's Embedded Binaries list.

There is no need to do any additional setup beyond adding the framework targets to Embedded Binaries.

Comments
  • Fix Linux randomUInt64 for Swift 4.1

    Fix Linux randomUInt64 for Swift 4.1

    Using private library methods is not sustainable. In Swift 4.1 the randomUInt64 function is broken for Linux. So I wrote an implementation which is a little bit unconventional and maybe a little bit slower than the old one but it is reliable and should work on all Linux and FreeBSD systems across different Swift versions. Like I said it may perform a little bit worse than the macOS implementation or the old one but because it will only be used once per process to generate the key, it doesn't really matter.

    opened by koraykoska 10
  • Different hash values every time for the same string

    Different hash values every time for the same string

    I had detect a problem with the hasher, every time I execute them I get a different hash for the same exact string:

    My simply test code:

    var hasherTest = SipHasher() hasherTest.append("Test") let hashVal = hasherTest.finalize()

    I run one time:

    Printing description of hashVal: 434885335948154737

    Then I run again:

    Printing description of hashVal: -3387410001051536137

    And so on, the hash value is always different, happend on Device and Simulator.

    If I use several hashers in the same execution, then I get the same value, but when I run the code again, values are not the same than in the previous execution.

    I am using version 1.2.

    opened by daniel-lahoz 1
  • v1.2.0 violates semantic versioning

    v1.2.0 violates semantic versioning

    The latest SipHash, 1.2.0, requires Swift 4.

    The last version of BigInt to support Swift 3, v2.1.2, depended on SipHash ~> 1.1. This means that SipHash 1.2.0 is now being used by CocoaPods, which is incompatible and results in failed compilation.

    Seems like v2.0.0 would've been a better version to use for this breaking change.


    For those that are having the same issue with BigInt, just add SipHash explicitly to your Podfile. You can just specify pod 'SipHash', '1.1.2' to pin that version and prevent CocoaPods from implicitly choosing a higher version.

    opened by allewun 1
  • Fix for installing Swift4 branch from CocoaPods

    Fix for installing Swift4 branch from CocoaPods

    The current 'master' of SipHash uses a folder named 'sources' for the source code to SipHash. The swift4 branch now has that code in a folder named 'SipHash', but the podspec wasn't updated to reflect this. This caused 'pod install' of the swift4 branch to not download the Swift code for SipHash, making the pod not buildable.

    This also prevented manual Podfile overrides of BigInt's SipHash dependency, as it would result in an invalid SipHash module.

    Once this is merged, installing SipHash via Podfile will work on the Swift4 branch (allowing BigInt for swift4 to be compilable via a Podfile override).

    Related BigInt issue: https://github.com/attaswift/BigInt/issues/22

    opened by amyleecodes 1
  • UnsafeRawBufferPointer errors when building

    UnsafeRawBufferPointer errors when building

    I installed SipHash through BigInt 3.1 with Cocoapods and got 2 errors when building the project. I'm using XCode 9.2, deployment target is ios11.2 (Swift 4).

    ! Cannot invoke initializer for type 'UnsafeRawBufferPointer' with an argument list of type '(rebasing: Slice<UnsafeRawBufferPointer>)'
    
    ! Value of type 'UnsafeMutableRawBufferPointer' has no member 'copyMemory'
    

    capture d ecran 2018-08-12 a 13 24 29

    capture d ecran 2018-08-12 a 13 23 56

    I both cleaned my build folder (Cmd+Shift+K) and did again a pod install but the issue persists.

    opened by romain64 5
Releases(v1.2.2)
  • v1.2.2(Jun 8, 2018)

  • v1.2.1(May 27, 2018)

  • v1.2.0(Sep 7, 2017)

    This release contains the following changes:

    • The package requires Swift 4.
    • SipHasher now has a method for appending slices of UnsafeRawBufferPointers.
    • In the supplied Xcode project, bundle identifiers have been updated. The new ones start with org.attaswift..

    Note that the URL to the package's Git repository has changed; please update your references.

    Source code(tar.gz)
    Source code(zip)
  • v1.1.2(May 5, 2017)

  • v1.1.1(Feb 7, 2017)

  • v1.1.0(Nov 23, 2016)

    This release contains the following changes:

    • SipHasher now supports appending optional values directly.
    • The deployment target for Carthage and standalone builds was set back to iOS 8.0 and macOS 10.9, the earliest possible OS versions for Swift frameworks. This change does not affect CocoaPod builds, which already had the same settings.
    Source code(tar.gz)
    Source code(zip)
  • v1.0.0(Nov 15, 2016)

Owner
A collection of useful Swift packages
null
Swift package wrapping the OpenWall BCrypt hashing algorithm

SwiftBCrypt A simple Swift Package wrapping the OpenWall BCrypt hashing algorithm. Generate Salt let bcryptSalt = try BCRypt.makeSalt() Hash Phrases

Tanner Silva 1 Jul 8, 2022
Cybr/Secure - A simple but powerful secure password generator

A simple but powerful secure password generator. You get the option of password length (10 to 20 characters) and whether you include numbers, symbols, uppercase and/or lowercase letters. Simply tap the lock icon to generate a secure password and then tap to copy the password.

Mykel Agathos 1 Feb 16, 2022
Easy to use cryptographic framework for data protection: secure messaging with forward secrecy and secure data storage. Has unified APIs across 14 platforms.

Themis provides strong, usable cryptography for busy people General purpose cryptographic library for storage and messaging for iOS (Swift, Obj-C), An

Cossack Labs 1.6k Dec 30, 2022
Simple, secure password and data management for individuals and teams

Padloc Simple, secure password and data management for individuals and teams (formerly known as Padlock). This repo is split into multiple packages: P

Padloc 2.1k Jan 8, 2023
A lightweight stochastic optimizer based on slime mold (Slime Mold Algorithm)

Slime This is a Swift implementation of a Slime Mold Algorithm - a stochastic optimizer - generally based on this paper The only dependency required b

Ethan J 4 Aug 6, 2022
CryptoSwift is a growing collection of standard and secure cryptographic algorithms implemented in Swift

CryptoSwift Crypto related functions and helpers for Swift implemented in Swift. (#PureSwift) Note: The master branch follows the latest currently rel

Marcin Krzyzanowski 9.4k Jan 5, 2023
PassDrop is a fully-featured secure password management system, compatible with the free KeePass 1.x (Classic) and multi-platform KeePassX desktop applications.

passdrop This is a modern, updated build of Rudis Muiznieks's PassDrop application. PassDrop is a fully-featured secure password management system, co

Chad Austin 33 Sep 23, 2022
The minimalistic, secure and open-source two-factor authentication app.

Einmal /ˈainmaːl/ German: once The minimalistic, secure and open-source two-factor authentication app. Features ♻️ Cross-platform — available on Andro

Incipher 75 Aug 21, 2022
Helps you define secure storages for your properties using Swift property wrappers.

?? Secure Property Storage Helps you define secure storages for your properties using Swift property wrappers. ?? Features All keys are hashed using S

Alex Rupérez 443 Jan 4, 2023
PGPro can encrypt and decrypt messages as well as manage all your OpenPGP keys. It is free, simple and lightweight. Everything stays on your device. PGPro is made in Switzerland.

PGPro can encrypt and decrypt messages as well as manage all your OpenPGP keys. It is free, simple and lightweight. Everything stays on your device. P

Luca Näf 250 Jan 4, 2023
Simple Swift wrapper for Keychain that works on iOS, watchOS, tvOS and macOS.

KeychainAccess KeychainAccess is a simple Swift wrapper for Keychain that works on iOS and OS X. Makes using Keychain APIs extremely easy and much mor

Kishikawa Katsumi 7.2k Dec 30, 2022
A simple Swift Keychain Wrapper for iOS, watchOS, and OS X.

Latch A simple Swift 2.0 Keychain Wrapper for iOS, watchOS 2, and OS X. Usage A proper example of how to use Latch can be seen in the tests. import La

Danielle 56 Oct 25, 2022
Simple Objective-C wrapper for the keychain that works on Mac and iOS

SAMKeychain SAMKeychain is a simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system Keyc

Sam Soffes 5.4k Dec 29, 2022
TouchEncryptedJson - Simple project that accepts an input and encrypts it with the TouchID on a Mac

TouchEncryptedJson Simple project that accepts an input and encrypts it with the

Charles Edge 2 Aug 29, 2022
A simple way of doing both symmetric and asymmetric crypto without the headache

Simple Swift Crypto I needed a simple way of doing both symmetric and asymmetric

Joe Hinkle 6 Dec 19, 2022
A simple wrapper for the iOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift.

SwiftKeychainWrapper A simple wrapper for the iOS / tvOS Keychain to allow you to use it in a similar fashion to User Defaults. Written in Swift. Prov

Jason 1.5k Dec 30, 2022
Very simple swift wrapper for Biometric Authentication Services (Touch ID) on iOS.

SimpleTouch Very simple swift wrapper for Biometric Authentication Services (Touch ID) on iOS. Sample Project There is a SimpleTouchDemo target define

Simple Machines 117 Nov 15, 2022
A super simple tool for macOS Swift developers to check validity of a Gumroad-issued software license keys

Gumroad License Validator Overview A super simple tool for macOS Swift developers to check validity of a Gumroad-issued software license keys Requirem

Daniel Kašaj 13 Sep 2, 2022
Swift HybridCrypto is simple customizable implementation of hybrid cryptography (AES+RSA+Hash) recommended by OWASP.

HybridCrypto (Swift) HybridCrypto is simple implementation of hybrid cryptography following recommendations by OWASP. Prerequisites: Minimum iOS SDK:

UTNGY Pisal 2 Sep 6, 2022