Skip to content

Instantly share code, notes, and snippets.

@nesimtunc
Created October 15, 2020 12:27
Show Gist options
  • Save nesimtunc/2958eef995c0012279d4054f12a66ff8 to your computer and use it in GitHub Desktop.
Save nesimtunc/2958eef995c0012279d4054f12a66ff8 to your computer and use it in GitHub Desktop.
A Keychain Wrapper for String Key and Value to save sensitive data in Apple Keychain
import Foundation
import Security
public enum KeychainWrapperError: Error {
case emptyKeyOrValue
case failure(status: OSStatus)
}
class KeychainWrapper {
public func set(string: String, forKey key: String) throws {
guard !string.isEmpty && !key.isEmpty else {
throw KeychainWrapperError.emptyKeyOrValue
}
do{
try removeString(forKey: key)
} catch {
throw error
}
var qd = setupQueryDictionary(forKey: key)
qd[kSecValueData as String] = string.data(using: .utf8)
let status = SecItemAdd(qd as CFDictionary, nil)
if status != errSecSuccess {
throw KeychainWrapperError.failure(status: status)
}
}
public func get(forKey key: String) throws -> String? {
guard !key.isEmpty else {
throw KeychainWrapperError.emptyKeyOrValue
}
var qd = setupQueryDictionary(forKey: key)
qd[kSecReturnData as String] = kCFBooleanTrue
qd[kSecMatchLimit as String] = kSecMatchLimitOne
var data: AnyObject?
let status = SecItemCopyMatching(qd as CFDictionary, &data)
if status != errSecSuccess {
throw KeychainWrapperError.failure(status: status)
}
let result: String?
if (data as? Data) != nil {
result = String(data: data as! Data, encoding: .utf8)
} else {
result = nil
}
return result
}
public func removeString(forKey key: String) throws {
guard !key.isEmpty else {
throw KeychainWrapperError.emptyKeyOrValue
}
let qd = setupQueryDictionary(forKey: key)
let status = SecItemDelete(qd as CFDictionary)
if status != errSecSuccess {
throw KeychainWrapperError.failure(status: status)
}
}
private func setupQueryDictionary(forKey key: String) -> [String: Any] {
var queryDictionary:[String: Any] = [kSecClass as String: kSecClassGenericPassword]
queryDictionary[kSecAttrAccount as String] = key.data(using: .utf8)
return queryDictionary
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment