Last active
April 9, 2022 18:42
-
-
Save adamzarn/264a88dd4e0ff6bbde0af1b7a509a662 to your computer and use it in GitHub Desktop.
A class that makes it easy to store and retrieve string values from the Keychain
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
/* Example Usage: | |
Get | |
---------------------------- | |
let token = Keychain[.token] | |
Set | |
---------------------------- | |
Keychain[.token] = value | |
Keychain[.token] = nil | |
*/ | |
enum KeychainKey: String { | |
case token | |
} | |
class Keychain { | |
class subscript(key: KeychainKey) -> String? { | |
get { | |
return Keychain.getString(valueForKey: key.rawValue) | |
} | |
set { | |
if let newValue = newValue { | |
Keychain.setString(value: newValue, forKey: key.rawValue) | |
} else { | |
Keychain.removeString(forKey: key.rawValue) | |
} | |
} | |
} | |
class func setString(value: String, forKey key: String) { | |
let data = Data(value.utf8) | |
let query = getSetStringQuery(key: key, data: data) | |
SecItemDelete(query as CFDictionary) | |
SecItemAdd(query as CFDictionary, nil) | |
} | |
class func removeString(forKey key: String) { | |
let query = getSetStringQuery(key: key) | |
SecItemDelete(query as CFDictionary) | |
} | |
class func getString(valueForKey key: String) -> String? { | |
let query = getGetStringQuery(key: key) | |
var dataTypeRef: AnyObject? = nil | |
let status: OSStatus = SecItemCopyMatching(query as CFDictionary, &dataTypeRef) | |
if status == noErr { | |
guard let data = dataTypeRef as? Data else { return nil } | |
return String(data: data, encoding: .utf8) | |
} else { | |
return nil | |
} | |
} | |
private class func getSetStringQuery(key: String, data: Data? = nil) -> CFDictionary { | |
return [kSecClass as String: kSecClassGenericPassword as String, | |
kSecAttrAccount as String: key, | |
kSecValueData as String: data ?? Data()] as CFDictionary | |
} | |
private class func getGetStringQuery(key: String) -> CFDictionary { | |
return [kSecClass as String: kSecClassGenericPassword, | |
kSecAttrAccount as String: key, | |
kSecReturnData as String: kCFBooleanTrue!, | |
kSecMatchLimit as String: kSecMatchLimitOne] as CFDictionary | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment