Enumerar todos los elementos de llavero en mi aplicación de iOS

¿Cuál es la forma más sencilla de progtwigr (desde mi aplicación) todos los elementos almacenados en el llavero?

Probablemente tiene algo que ver con SecItemCopyMatching (), pero la documentación para esa función no es muy clara (y no pude encontrar una muestra decente en la web).

SecItemCopyMatching es la llamada correcta para eso. Primero construimos nuestro diccionario de consulta para que los atributos de los elementos se devuelvan en los diccionarios y se devuelvan todos los elementos:

 NSMutableDictionary *query = [NSMutableDictionary dictionaryWithObjectsAndKeys: (__bridge id)kCFBooleanTrue, (__bridge id)kSecReturnAttributes, (__bridge id)kSecMatchLimitAll, (__bridge id)kSecMatchLimit, nil]; 

Como SecItemCopyMatching requiere al menos la clase de los SecItem s SecItem , creamos una matriz con todas las clases …

 NSArray *secItemClasses = [NSArray arrayWithObjects: (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClassInternetPassword, (__bridge id)kSecClassCertificate, (__bridge id)kSecClassKey, (__bridge id)kSecClassIdentity, nil]; 

… y para cada clase, configure la clase en nuestra consulta, llame a SecItemCopyMatching y registre el resultado.

 for (id secItemClass in secItemClasses) { [query setObject:secItemClass forKey:(__bridge id)kSecClass]; CFTypeRef result = NULL; SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); NSLog(@"%@", (__bridge id)result); if (result != NULL) CFRelease(result); } 

En el código de producción, debe verificar que OSStatus devuelto por SecItemCopyMatching sea errSecItemNotFound (no se encontraron elementos) o errSecSuccess (se errSecSuccess al menos un elemento).

Swift 3+ versión que devuelve también las claves (kSecAttrAccount):

 open func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { let query: [String: Any] = [ kSecClass : secClass, kSecReturnData : kCFBooleanTrue, kSecReturnAttributes : kCFBooleanTrue, kSecReturnRef : kCFBooleanTrue, kSecMatchLimit : kSecMatchLimitAll ] var result: AnyObject? let lastResultCode = withUnsafeMutablePointer(to: &result) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) } var values = [String:String]() if lastResultCode == noErr { let array = result as? Array> for item in array! { if let key = item[kSecAttrAccount] as? String, let value = item[kSecValueData] as? Data { values[key] = String(data: value, encoding:.utf8) } } } return values } 

Versión de Swift 3 con xcode 9.1

 func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { let query: [String: Any] = [ kSecClass as String : secClass, kSecReturnData as String : kCFBooleanTrue, kSecReturnAttributes as String : kCFBooleanTrue, kSecReturnRef as String : kCFBooleanTrue, kSecMatchLimit as String : kSecMatchLimitAll ] var result: AnyObject? let lastResultCode = withUnsafeMutablePointer(to: &result) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) } var values = [String:String]() if lastResultCode == noErr { let array = result as? Array> for item in array! { if let key = item[kSecAttrAccount as String] as? String, let value = item[kSecValueData as String] as? Data { values[key] = String(data: value, encoding:.utf8) } } } return values } 

Se puede llamar así:

 debugPrint(getAllKeyChainItemsOfClass(kSecClassGenericPassword as String)) 

Swift 4 actualización a @Cosmin respuesta

 open func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { let query: [String: Any] = [ kSecClass as String : secClass, kSecReturnData as String : kCFBooleanTrue, kSecReturnAttributes as String : kCFBooleanTrue, kSecReturnRef as String : kCFBooleanTrue, kSecMatchLimit as String: kSecMatchLimitAll ] var result: AnyObject? let lastResultCode = withUnsafeMutablePointer(to: &result) { SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0)) } var values = [String:String]() if lastResultCode == noErr { let array = result as? Array> for item in array! { if let key = item[kSecAttrAccount as String] as? String, let value = item[kSecValueData as String] as? Data { values[key] = String(data: value, encoding:.utf8) } } } return values }