2012-07-26 238 views
19

我想将私钥添加到iOS钥匙串中。证书(公钥)工作正常,但私钥拒绝...我完全困惑为什么下面的代码不起作用。将私钥添加到iOS钥匙串

首先我检查如果当前密钥(=,所述钥匙链的情况下,密钥是键/值存储)是钥匙串“自由”。然后我要添加私钥。

CFStringRef labelstring = CFStringCreateWithCString(NULL, [key cStringUsingEncoding:NSUTF8StringEncoding], kCFStringEncodingUTF8); 

NSArray* keys = [NSArray arrayWithObjects:(__bridge id)kSecClass,kSecAttrLabel,kSecReturnData,kSecAttrAccessible,nil]; 
NSArray* values = [NSArray arrayWithObjects:(__bridge id)kSecClassKey,labelstring,kCFBooleanTrue,kSecAttrAccessibleWhenUnlocked,nil]; 
NSMutableDictionary* searchdict = [NSMutableDictionary dictionaryWithObjects:values forKeys:keys]; 

CFRelease(labelstring); 

NSMutableDictionary *query = searchdict; 


CFTypeRef item = NULL; 
OSStatus error = SecItemCopyMatching((__bridge_retained CFDictionaryRef) query, &item); 

if (error) 
{ 
    NSLog(@"Error: %ld (statuscode)", error); 
} 

if(error != errSecItemNotFound) 
{ 
    SecItemDelete((__bridge_retained CFDictionaryRef) query); 
} 

[query setObject:(id)data forKey:(__bridge id)kSecValueData]; 

OSStatus status = SecItemAdd((__bridge_retained CFDictionaryRef) query, &item); 

if(status) 
{ 
    NSLog(@"Keychain error occured: %ld (statuscode)", status); 
    return NO; 
} 

调试输出如下:

2012-07-26 15:33:03.772 App[15529:1b03] Error: -25300 (statuscode) 
2012-07-26 15:33:11.195 App[15529:1b03] Keychain error occured: -25299 (statuscode) 

第一错误代码-25300表示errSecItemNotFound。所以这个键没有存储值。然后,当我尝试将私钥添加到钥匙串时,我得到-25299这意味着errSecDuplicateItem。我不明白。这是为什么发生?

有没有人有一个线索或暗示对此有何看法?

苹果的错误代码:提前

errSecSuccess    = 0,  /* No error. */ 
errSecUnimplemented   = -4,  /* Function or operation not implemented. */ 
errSecParam     = -50,  /* One or more parameters passed to a function where not valid. */ 
errSecAllocate    = -108, /* Failed to allocate memory. */ 
errSecNotAvailable   = -25291, /* No keychain is available. You may need to restart your computer. */ 
errSecDuplicateItem   = -25299, /* The specified item already exists in the keychain. */ 
errSecItemNotFound   = -25300, /* The specified item could not be found in the keychain. */ 
errSecInteractionNotAllowed = -25308, /* User interaction is not allowed. */ 
errSecDecode     = -26275, /* Unable to decode the provided data. */ 
errSecAuthFailed    = -25293, /* The user name or passphrase you entered is not correct. */ 

谢谢!

更新#1:我已经想通了,它仅适用于第一次。即使数据和密钥不同,在第一次存储到钥匙串后,我无法存储其他密钥。

+0

我面对完全一样的问题。使用SecItemAdd添加第一个密钥没有问题,然后任何对SecItemAdd的连续调用都会失败,并返回errSecDuplicateItem,尽管SecItemCopyMatching返回了errSecItemNotFound。你有没有找到解决方案呢? – 100grams 2013-01-08 10:47:18

回答

8

下面的代码为我工作:

NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 
[query setObject:(id)kSecClassKey forKey:(id)kSecClass]; 
[query setObject:(id)kSecAttrAccessibleWhenUnlocked forKey:(id)kSecAttrAccessible]; 
[query setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData]; 

//adding access key 
[query setObject:(id)key forKey:(id)kSecAttrApplicationTag]; 


//removing item if it exists 
SecItemDelete((CFDictionaryRef)query); 

//setting data (private key) 
[query setObject:(id)data forKey:(id)kSecValueData]; 

CFTypeRef persistKey; OSStatus status = SecItemAdd((CFDictionaryRef)query, &persistKey); 

if(status) { 
    NSLog(@"Keychain error occured: %ld (statuscode)", status); 
    return NO; 
} 
+0

删除一个Keychain项目只是为了添加一个具有相同信息的项目是不好的做法。我不记得具体的原因,但我相信在尝试这样做时可能会导致冲突。 – Joey 2014-04-12 06:01:19

+0

我曾与一位在去年的WWDC上从事Keychain工作的苹果员工谈过,他告诉我,实际上他们现在还没有提供另外一种方法来实现这一点,但他们有一个专用API用于他们将发布_soon_。 .. – Chris 2014-04-13 07:55:14

+1

我不知道你的意思是克里斯。我有同样的问题,并能够修复我的代码,以正确找到现有的项目。我的问题是我在添加它时将其定义为可通过iCloud进行同步,但在搜索时没有在查询中包括该内容,因此找不到匹配项。我不必删除并重新添加。 – Joey 2014-04-13 08:14:14

1

很抱歉,但我永远无法调试代码。 Apple提供了一些示例代码(KeychainItemWrapper),它允许您保存一个字符串(我记得)。它在处理钥匙链方面有很大的帮助。 Web上有一个要求是该类的修改版本,但保存和恢复字典(作为数据对象存档,这是Apple代码对字符串的作用)。这可让您将多个项目保存到钥匙串的一个界面中。要点是这里Keychain for NSDictionary/data

+1

谢谢,但它需要存储为'kSecClassKey'(和相应的证书作为'kSecClassCertificate')。我知道Apple提供了这个示例代码,用于将用户凭证(但只是字符串)存储到钥匙串中。考虑到人们想要验证一个证书或者使用'kSecClassKey'的附加保护,它不能使用Apple示例代码或链接的方法进行存储。不过,我想我已经找到了一个解决方案,但必须在我发布之前对其进行验证。 – Chris 2012-07-27 05:41:28

+1

根据我的经验,钥匙串包装不允许将多个项目保存到同一个钥匙串组中。这造成了一些重大的挫折,但一个解决方案可以在这里找到:http://stackoverflow.com/questions/11055731/ios-save-multiple-passwords-in-keychain?lq=1 – rob 2012-09-27 16:02:22

+0

这很有趣 - 因为我在做与我的应用程序中的字典并保存电子邮件,密码和与用户相关的另一个上下文。但是我修改了苹果的代码并不是很多 - 你可以在我的答案中的链接中看到它。这是工作代码,现在有成千上万的电话(不是数百万:-() – 2012-09-27 16:53:26