Skip to content

Instantly share code, notes, and snippets.

@cipolleschi
Created May 4, 2020 09:52
Show Gist options
  • Save cipolleschi/41cea57f4fbd41da9b03f223ff27b795 to your computer and use it in GitHub Desktop.
Save cipolleschi/41cea57f4fbd41da9b03f223ff27b795 to your computer and use it in GitHub Desktop.
func createQuery(for serivce: String) -> [String: Any] {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecReturnAttributes as String: true,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitAll
]
return query
}
func get(service: String, type: Int) throws -> [(account: String, password: Data)] {
// 1. create the query to retrieve the type
var query = createQuery(for: serive)
query[kSecAttrType as String] = type
// 2. retrieve the data
var extractedData: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &extractedData)
// 3. handle the result
guard status == errSecItemNotFound || status == errSecSuccess else {
throw Error.otherError(status)
}
guard status != errSecItemNotFound else {
return []
}
let array = extractedData as! CFArray
let dictionaries: [[String: Any]] = array.toSwiftArray()
let pairs = dictionaries.compactMap { $0.accountPasswordPair }
return pairs
}
func get(service: String, label: String) throws -> [(account: String, password: Data)] {
var query = createQuery(for: serive)
query[kSecAttrLabel as String] = label
var extractedData: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &extractedData)
guard status == errSecItemNotFound || status == errSecSuccess else {
throw Error.otherError(status)
}
guard status != errSecItemNotFound else {
return []
}
let array = extractedData as! CFArray
let dictionaries: [[String: Any]] = array.toSwiftArray()
let pairs = dictionaries.compactMap { $0.accountPasswordPair }
return pairs
}
// MARK: - Helper extensions to extract data from CFArray and Dictionaries
extension CFArray {
func toSwiftArray<T>() -> [T] {
let array = Array<AnyObject>(_immutableCocoaArray: self)
return array.compactMap { $0 as? T }
}
}
extension Dictionary where Key == String, Value == Any {
var accountPasswordPair: (account: String, password: Data)? {
guard
let account = self[kSecAttrAccount as String] as? String,
let password = self[kSecValueData as String] as? Data
else {
return nil
}
return (account, password)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment