Read-only mirror of https://github.com/swiyu-admin-ch/pbkdf2-swift — Bundesamt für Justiz. Issues & pull requests at the source.
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-03-27 19:44:35 +01:00
Sources/Pbkdf2 📦 Automated commit made by the 'Build Swift language bindings' GitHub action workflow 2026-03-27 09:38:13 +00:00
.gitignore Initial commit 2026-03-24 14:46:44 +01:00
CONTRIBUTING.md Initial commit 2026-03-24 14:46:44 +01:00
LICENSE.md Initial commit 2026-03-24 14:46:44 +01:00
Package.swift 📦 Automated commit made by the 'Build Swift language bindings' GitHub action workflow 2026-03-27 09:38:13 +00:00
README.md Update README.md 2026-03-27 19:44:35 +01:00

Public Beta banner

pbkdf2 (password hashing) for Swift applications

This project contains language bindings required for loading and using the swiyu pbkdf2 library (Rust) in Swift applications.

Here is a simple usage example:

import Foundation

import pbkdf2

struct HexEncodingOptions: OptionSet {
    let rawValue: Int
    static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}

extension Sequence where Element == UInt8 {
    func hexEncodedString(options: HexEncodingOptions = []) -> String {
        let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
        return self.map { String(format: format, $0) }.joined()
    }
}

var pbkdf2 = Pbkdf2()

let password: Data? = "password".data(using: .utf8)
let salt: Data? = "salt".data(using: .utf8)

var tryError: Error?
do {
    // hash + verify
    var passwordHashAsString = try pbkdf2.hashPasswordAsString(password: password!, salt: salt!) // PHC format
    let verifyPassword = try pbkdf2.verifyPassword(password: password!, passwordHash: passwordHashAsString)
    assert(verifyPassword)
    
    // Test vectors (Test Case 2) from:
    // https://github.com/brycx/Test-Vector-Generation/blob/master/PBKDF2/pbkdf2-hmac-sha2-test-vectors.md#test-case-2
    // Online generators (e.g., https://asecuritysite.com/pbkdf2/pb2) may be used as well.

    var pbkdf2Sha256 = Pbkdf2.newCustom(alg: Algorithm.pbkdf2Sha256, rounds: 2, outputLength: 20)
    var passwordHash = try pbkdf2Sha256.hashPassword(password: password!, salt: salt!)
    assert("ae4d0c95af6b46d32d0adff928f06dd02a303f8e" == passwordHash.hexEncodedString())

    var pbkdf2Sha512 = Pbkdf2.newCustom(alg: Algorithm.pbkdf2Sha512, rounds: 2, outputLength: 20)
    passwordHash = try pbkdf2Sha512.hashPassword(password: password!, salt: salt!)
    assert("e1d9c16aa681708a45f5c7c4e215ceb66e011a2e" == passwordHash.hexEncodedString())

    // Test vectors (Test Case 3) from:
    // https://github.com/brycx/Test-Vector-Generation/blob/master/PBKDF2/pbkdf2-hmac-sha2-test-vectors.md#test-case-3
    // Online generators (e.g., https://asecuritysite.com/pbkdf2/pb2) may be used as well.

    pbkdf2Sha256 = Pbkdf2.newCustom(alg: Algorithm.pbkdf2Sha256, rounds: 4096, outputLength: 20)
    passwordHash = try pbkdf2Sha256.hashPassword(password: password!, salt: salt!)
    assert("c5e478d59288c841aa530db6845c4c8d962893a0" == passwordHash.hexEncodedString())

    pbkdf2Sha512 = Pbkdf2.newCustom(alg: Algorithm.pbkdf2Sha512, rounds: 4096, outputLength: 20)
    passwordHash = try pbkdf2Sha512.hashPassword(password: password!, salt: salt!)
    assert("d197b1b33db0143e018b12f3d1d1479e6cdebdcc" == passwordHash.hexEncodedString())

} catch { tryError = error }
    guard nil == tryError else { fatalError(tryError.debugDescription) }

Contributions and feedback

We welcome any feedback on the code regarding both the implementation and security aspects. Please follow the guidelines for contributing found in CONTRIBUTING.

License

This project is licensed under the terms of the MIT license. See the LICENSE file for details.