You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
There are a few keychain wrappers around but for simple needs, you can write it yourself
Here is a basic implementation. I use actor to go with async/await, and a struct KeychainError to contain status code in case we want to deal with error cases.
accessGroup is to define kSecAttrAccessGroup to share keychain across your apps
publicactorKeychain{publicstructKeychainError:Error{letstatus:OSStatus}letservice:StringletaccessGroup:String?publicinit(
service:String,
accessGroup:String?=nil){self.service = service
self.accessGroup = accessGroup
}}
Since we need some common query parameters across few methods, I usually use helper method. We use kSecClassGenericPassword class so we set key to kSecAttrAccount
func baseQuery(key:String)->[CFString:Any]{varquery:[CFString:Any]=[:]query[kSecClass]= kSecClassGenericPassword
query[kSecAttrService]= service
query[kSecAttrAccount]= key
if let accessGroup {query[kSecAttrAccessGroup]= accessGroup
}return query
}
Below is how to get and set Data to keychain
func get(key:String)throws->Data{varquery=baseQuery(key: key)query[kSecMatchLimit]= kSecMatchLimitOne
query[kSecReturnAttributes]= kCFBooleanTrue
query[kSecReturnData]= kCFBooleanTrue
varobj:AnyObject?letstatus=SecItemCopyMatching(query asCFDictionary,&obj)
if status == errSecSuccess,let json = obj as?[CFString:AnyObject],let data =json[kSecValueData]as?Data{return data
}else{throwKeychainError(status: status)}}func set(key:String, data:Data)throws{do{
_ =tryget(key: key)tryupdate(key: key, data: data)}catchlet error as KeychainError{
if error.status == errSecItemNotFound {tryadd(key: key, data: data)}}}func delete(key:String)throws{letquery=baseQuery(key: key)letstatus=SecItemDelete(query asCFDictionary)
if status != errSecSuccess {throwKeychainError(status: status)}}privatefunc update(key:String, data:Data)throws{letquery=baseQuery(key: key)letupdates:[CFString:Any]=[
kSecValueData: data
]letstatus=SecItemUpdate(query asCFDictionary, updates asCFDictionary)
if status != errSecSuccess {throwKeychainError(status: status)}}privatefunc add(key:String, data:Data)throws{varquery=baseQuery(key: key)query[kSecValueData]= data
letstatus=SecItemAdd(query asCFDictionary,nil)
if status != errSecSuccess {throwKeychainError(status: status)}}
If there is no error, then OSStatus will be errSecSuccess which has value 0
There are a few keychain wrappers around but for simple needs, you can write it yourself
Here is a basic implementation. I use actor to go with async/await, and a struct
KeychainError
to contain status code in case we want to deal with error cases.accessGroup
is to define kSecAttrAccessGroup to share keychain across your appsSince we need some common query parameters across few methods, I usually use helper method. We use
kSecClassGenericPassword
class so we set key tokSecAttrAccount
Below is how to get and set Data to keychain
If there is no error, then
OSStatus
will beerrSecSuccess
which has value 0There are some other query attributes like
The text was updated successfully, but these errors were encountered: