import CommonCrypto import Foundation enum PinHash { private static let iterations: UInt32 = 100_000 private static let keyLength = 32 // 256 bits static func generateSalt() -> Data { var salt = Data(count: 16) _ = salt.withUnsafeMutableBytes { SecRandomCopyBytes(kSecRandomDefault, 16, $0.baseAddress!) } return salt } static func hash(_ input: String, salt: Data) -> String { var derivedKey = Data(count: keyLength) let inputData = Data(input.utf8) _ = derivedKey.withUnsafeMutableBytes { derivedPtr in inputData.withUnsafeBytes { inputPtr in salt.withUnsafeBytes { saltPtr in CCKeyDerivationPBKDF( CCPBKDFAlgorithm(kCCPBKDF2), inputPtr.baseAddress, inputData.count, saltPtr.baseAddress, salt.count, CCPseudoRandomAlgorithm(kCCPRFHmacAlgSHA256), iterations, derivedPtr.baseAddress, keyLength ) } } } return derivedKey.base64EncodedString() } static func verify(_ input: String, against storedHash: String, salt: Data) -> Bool { hash(input, salt: salt) == storedHash } }