2012-06-10 86 views
29

以编程方式(从我的应用程序中)获取存储在钥匙串中的所有项目的最简单方法是什么?枚举我的iOS应用程序中的所有钥匙串项目

它可能与SecItemCopyMatching()有关,但该函数的文档不是很清楚(我没有找到一个体面的样本在网上)。

回答

46

SecItemCopyMatching是正确的要求。首先,我们建立我们的查询字典,使得项目属性在字典回来了,这个返回的所有项目:

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

由于SecItemCopyMatching至少需要类返回SecItem S的,我们创造了所有的数组类...

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

...并为每个类,设置类在我们的查询,请致电SecItemCopyMatching,并记录结果。

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

在生产代码中,你应该检查由SecItemCopyMatching返回OSStatus或者是errSecItemNotFounderrSecSuccess(找不到项目)(至少一个项目被发现)。

+0

谢谢!还没有测试过,但看起来是正确的答案。 – noamtm

+2

是。我测试了它:) –

+0

我在iPhone和模拟器打印出来都是空的。还有什么我应该做的吗? – karim

3

斯威夫特3+版本,还返回键(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

在Xcode 9.2上使用Swift 3时,在'let key:String = item [kSecAttrAccount] as!字符串'无法将类型'__NSCFData'(0x109b30348)的值转换为'NSString'(0x1069030d0).'。我不知道为什么。 –

+1

更改设置键和值的行使得崩溃不会发生,尽管它消除了我不确定如何抽出的几个对象:'if let key = item [kSecAttrAccount] as?字符串,让value = item [kSecValueData]为?数据{' –

0

斯威夫特3版和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 
} 

可以这样调用:

debugPrint(getAllKeyChainItemsOfClass(kSecClassGenericPassword as String)) 
相关问题