2012-06-10 10 views
29

Jaki jest najprostszy sposób programowego (z poziomu mojej aplikacji) uzyskać wszystkie elementy przechowywane w pęku kluczy?Wyliczanie wszystkich elementów Keychain w mojej aplikacji iOS

Prawdopodobnie ma to coś wspólnego z SecItemCopyMatching(), ale dokumentacja dla tej funkcji nie jest bardzo jasna (i nie udało mi się znaleźć przyzwoitej próbki w Internecie).

Odpowiedz

46

SecItemCopyMatching to odpowiednie połączenie. Najpierw musimy zbudować nasz słownik zapytań tak, że atrybuty przedmiotów są zwracane w słownikach, a wszystkie elementy są zwracane:

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

Jak SecItemCopyMatching wymaga co najmniej klasa zwróconych SecItem s, tworzymy tablicę ze wszystkimi zajęcia ...

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

... i dla każdej klasy, ustawić klasę w naszym zapytaniu, zadzwoń SecItemCopyMatching i zaloguj wynik.

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); 
} 

W produkcji kodu, należy sprawdzić, czy OSStatus zwrócony przez SecItemCopyMatching jest albo errSecItemNotFound (nie znaleziono pozycji) lub errSecSuccess (przynajmniej jeden element został znaleziony).

+0

Dzięki! Nie testowałem jeszcze, ale wygląda na właściwą odpowiedź. – noamtm

+2

To jest. Testowałem to :) –

+0

Mam wszystkie null w druku zarówno na iPhone'a jak i na symulatorze. Czy jest coś, co powinienem zrobić? – karim

3

Swift 3+ wersja, która zwraca również klawisze (kSecAttrAccount):

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

Użycie Swift 3 w Xcode 9.2 powoduje awarię w 'let key: String = item [kSecAttrAccount] as! Łańcuch 'z' Nie można rzucić wartość typu "__NSCFData" (0x109b30348) na "NSString" (0x1069030d0). ". Nie jestem pewien dlaczego. –

+1

Zmiana linii, w której ustawiono klucz i wartość, spowodowała awarię, ale eliminuje kilka obiektów, których nie jestem pewien: "if let key = element [kSecAttrAccount] as? Łańcuch, wartość dopuszczalna = element [kSecValueData] jako? Dane { –

0

Swift 3 wersja z 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 
} 

można nazwać jak:

debugPrint(getAllKeyChainItemsOfClass(kSecClassGenericPassword as String)) 
Powiązane problemy