import CommonCrypto import Foundation extension Data { var bytes: [UInt8] { [UInt8](self) } } extension Array where Element == UInt8 { var data: Data { Data(self) } } extension Data { func hmac(key: Data) -> Data { var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) CCHmac(CCHmacAlgorithm(kCCHmacAlgSHA1), key.bytes, key.count, bytes, count, &digest) return Data(digest) } func sha1() -> Data { var digest = [UInt8](repeating: 0, count: Int(CC_SHA1_DIGEST_LENGTH)) withUnsafeBytes { _ = CC_SHA1($0.baseAddress, CC_LONG(self.count), &digest) } return digest.data } func sha256() -> Data { var digest = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH)) withUnsafeBytes { _ = CC_SHA256($0.baseAddress, CC_LONG(self.count), &digest) } return Data(digest) } func pbkdf2(salt: Data, rounds: Int) -> Data { var buff = [UInt8](repeating: 0, count: salt.count) (salt as NSData).getBytes(&buff, length: salt.count) buff.append(contentsOf: [0, 0, 0, 1]) var digest = buff.data.hmac(key: self) var result = digest for _ in 1 ..< rounds { digest = digest.hmac(key: self) for indx in 0 ..< digest.count { result[indx] ^= digest[indx] } } return result } func xor(other: Data) -> Data { let otherBytes = other.bytes var result = bytes for indx in 0 ..< result.count { result[indx] ^= otherBytes[indx] } return result.data } }