2012-06-10 29 views
29

¿Cuál es la forma más fácil de obtener programáticamente (desde mi aplicación) todos los elementos almacenados en el llavero?Enumerar todos los elementos de Llavero en mi aplicación iOS

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).

Respuesta

46

SecItemCopyMatching es la decisión correcta para eso. En primer lugar construimos nuestro diccionario consulta para que los atributos de los ítems se devuelven en los diccionarios, y que se devuelven todos los artículos:

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 devueltos SecItem s, creamos una matriz con todos 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, definen la clase en nuestra consulta, llaman SecItemCopyMatching y registrar 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, se debe comprobar que el OSStatus devuelto por SecItemCopyMatching es o bien errSecItemNotFound (artículos encontrados) o errSecSuccess (se encontró al menos un elemento).

+0

Gracias! Aún no lo he probado, pero parece ser la respuesta correcta. – noamtm

+2

Lo es. Lo probé :) –

+0

Tengo todo nulo en impresión tanto en iPhone como en simulador. ¿Hay algo más que debería hacer? – karim

3

Swift 3+ versión que vuelve también las teclas (kSecAttrAccount): Versión

open func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { 

     var 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<Dictionary<String, Any>> 

      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 
    } 
+0

Usando Swift 3 en Xcode 9.2 esto se bloquea en 'let key: String = item [kSecAttrAccount] as! String' con 'No se pudo convertir el valor del tipo '__NSCFData' (0x109b30348) en 'NSString' (0x1069030d0) .'. No estoy seguro por qué. –

+1

Al cambiar las líneas que establecen clave y valor a esto, no se produce el bloqueo, aunque elimina varios objetos de los que no estoy seguro cómo extraerlos: 'if let key = item [kSecAttrAccount] as? String, let value = item [kSecValueData] as? Datos {' –

0

Swift 3 con Xcode 9,1

func getAllKeyChainItemsOfClass(_ secClass: String) -> [String:String] { 

    var 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<Dictionary<String, Any>> 

     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 
} 

puede ser llamado como:

debugPrint(getAllKeyChainItemsOfClass(kSecClassGenericPassword as String)) 
Cuestiones relacionadas