将私钥添加到 iOS 钥匙串中
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11670647/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Adding private key into iOS Keychain
提问by Chris
I am trying to add a private key into the iOS keychain. The certificate (public key) works fine but the private key refuses... I am totally confused why the following code does not work.
我正在尝试将私钥添加到 iOS 钥匙串中。证书(公钥)工作正常,但私钥拒绝......我完全困惑为什么下面的代码不起作用。
First I am checking if the current key (=key in case of that the Keychain is a key/value store) is 'free' in the Keychain. Then I am going to add the private key.
首先,我正在检查当前密钥(如果钥匙串是键/值存储的情况下的键)在钥匙串中是否“空闲”。然后我要添加私钥。
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;
}
The debug output is the following:
调试输出如下:
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)
The first error code -25300
represents errSecItemNotFound
. So there is no value stored for this key. Then, when I try to add the private key into the Keychain I get -25299
which means errSecDuplicateItem
. I do not understand this. Why is this happening?
第一个错误代码-25300
代表errSecItemNotFound
. 所以没有为这个键存储值。然后,当我尝试将私钥添加到钥匙串中时,我得到-25299
这意味着 errSecDuplicateItem
. 我不明白。为什么会这样?
Does anyone have a clue or hint on this?
有没有人对此有线索或提示?
Apple's error codes:
苹果的错误代码:
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. */
Thanks in advance!
提前致谢!
Update #1: I've figured out that it works only for the first time. Even when data and key is different, after the first time stored into the keychain I cannot store further keys.
更新 #1:我发现它只在第一次有效。即使数据和密钥不同,在第一次存储到钥匙串中后,我也无法存储更多的密钥。
采纳答案by Chris
The following code worked for me:
以下代码对我有用:
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;
}
回答by David H
Sorry but I'll never be able to debug your code. Apple provides some sample code (KeychainItemWrapper) which lets you save one string (I recall). Its a big help dealing with the key chain. There is a gist on the web that is a modified version of that class, but saves and restores a dictionary (archived as a data object, which is what the Apple code does to the string). This lets you save multiple items in one interface to the keychain. The gist is here Keychain for NSDictionary/data
抱歉,我永远无法调试您的代码。Apple 提供了一些示例代码 (KeychainItemWrapper),可以让您保存一个字符串(我记得)。它对处理钥匙链有很大帮助。网上有一个 gist 是那个类的修改版本,但保存和恢复了一个字典(存档为数据对象,这是苹果代码对字符串所做的)。这使您可以在一个界面中将多个项目保存到钥匙串。要点在这里是 NSDictionary/data 的钥匙串