2012-10-22 44 views
2

我在我的應用程序的文檔文件夾中有一個PKCS12文件,其中包含一個證書和一個私鑰。 我可以打開此.p12文件,提取標識對象並顯示一些信息,這要歸功於Apple的文檔(https://developer.apple.com/library/ios/#documentation/Security/Conceptual/CertKeyTrustProgGuide/iPhone_Tasks/iPhone_Tasks .html#// apple_ref/doc/uid/TP40001358-CH208-DontLinkElementID_10)如何將已添加的SecIdentityRef更新爲iOS應用程序的鑰匙串?

我現在要做的是將此標識存儲到鑰匙串中,以便稍後使用它。我已經閱讀了iOS Keychain上的很多不同的東西,我很難弄清它是如何工作的。

Apple的代碼似乎使用persistent_ref來檢索存儲在Keychain中的Identity。但我真的不明白這是什麼...它是一個簡單的參考,如記憶參考?如果是這種情況,設備重新啓動時會發生什麼?

無法找到關於此的更多信息我試圖通過使用kSecAttr屬性以不同方式執行此操作。 目前的代碼工作正常添加身份到鑰匙串:

NSMutableDictionary * dictionary = [[[NSMutableDictionary alloc] init] autorelease]; 

[dictionary setObject:@"LABEL" forKey:kSecAttrLabel]; 

[dictionary setObject:(id)newIdentity forKey:(id)kSecValueRef]; 

OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL); 

但是,如果我嘗試添加了第二遍我收到-25299錯誤是「精」,因爲它已經存在。

NSMutableDictionary *searchDictionary = [[[NSMutableDictionary alloc] init] autorelease]; 
[searchDictionary setObject:@"LABEL" forKey:kSecAttrLabel]; 
[searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; 
[searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnRef]; 

NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init]; 
[updateDictionary setObject:(id)newIdentity forKey:(id)kSecValueRef]; 

OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,(CFDictionaryRef)updateDictionary); 

有了這個代碼,我收到了-50狀態錯誤顯然是因爲我有無效的參數......哪一個:我試圖通過這樣的更新處理呢?爲什麼?我能做些什麼來正確更新我的鑰匙串?

編輯:建議我試圖在添加它之前刪除現有的元素,但我堅持使用相同的狀態代碼(-50)。下面是我試過的代碼:

NSMutableDictionary *searchDictionary = [self setupSearchDirectoryForIdentifier:identifier]; 
OSStatus status = SecItemDelete((CFDictionaryRef)searchDictionary); 
NSAssert(status == noErr, @"Problem deleting current keychain item."); 

setupSearchDirectoryForIdentifier只需創建一個NSDictionnary與我的項目的標籤:

- (NSMutableDictionary *)setupSearchDirectoryForIdentifier:(NSString *)identifier { 

    // Setup dictionary to access keychain. 
    NSMutableDictionary *searchDictionary = [[[NSMutableDictionary alloc] init] autorelease]; 

    [searchDictionary setObject:identifier forKey:kSecAttrLabel]; 

    return searchDictionary; 
} 

謝謝

PS:我上的Xcode 4.2/iPad的開發5.1.1

回答

3

SecIdentityRef S,SecKeyRef S和類似Sec...Ref值是鑰匙扣的短暫交涉項目。當應用程序退出或保留計數達到零時,它們就會失效。它們不能直接保存在持久性存儲中。

另一方面,持久引用是一段CFDataRef,您可以稍後使用它來檢索特定的鑰匙串項目。您可以將其存儲在文件中,位於NSUserDefaults或您喜歡的任何其他位置。當應用程序退出或設備重新啓動時,它不會失效。 (但是,當鑰匙串本身被移除時(即,當設備被恢復時),當它所涉及的項目被刪除或當其中一個項目的識別屬性被修改時,持久性參考可能變得無效)。

Apple's sample代碼使用SecItemAdd的第二個參數來檢索對添加到鑰匙串的項目的持久引用。這大概存儲在NSUserDefaults。鑑於持久的參考,應用程序可以稍後使用SecItemCopyMatching將其轉換爲它可以使用的SecIdentityRef

請注意,如果你不想使用持久引用,如果您願意,您還可以選擇根據標籤或任何其他識別屬性檢索鑰匙串項目。

SecItemUpdate可能失敗,因爲SecIdentityRef不是真正的鑰匙串項目。這只是一個僞項目,當一個公鑰和它的相關私鑰都在鑰匙串上時,這個僞項目就構成了。因此,更新它沒有多大意義 - 它沒有任何屬性。其所有屬性都從其關聯的SecCertificateRef(證書)和SecKeyRef(私鑰)繼承。更新這些項目而不是身份應該起作用。 (但是簡單地正確創建項目比較容易:您可以通過將其添加到SecItemAdd的第一個參數中來初始化任何屬性。)或者,您可以嘗試簡單地刪除標識(SecItemDelete),然後重新將其添加到鑰匙扣。

+0

剛編輯我的問題。我試圖刪除之前添加項目,但我仍然有相同的狀態代碼,即使我只在searchDictionary中有一個元素。對我來說沒有多大意義。 – Anth0

4

即使這是一箇舊帖子,當我在處理鑰匙鏈中的身份(用於SSL客戶端身份驗證)時最近出現類似問題時,我提供了我自己的體驗(使用XCode 5.0.1)因爲對此的支持似乎仍然非常混亂。

SecItemAdd的確必須使用很少的按鍵。 kSecValueRef(帶有身份)當然是強制性的,可以選擇kSecAttrLabel。使用其他幾個密鑰(例如kSecClass)導致無提示失敗,即沒有錯誤報告,但沒有添加身份。這很混亂。

我沒有成功使用SecItemUpdate這樣的身份。我所有的嘗試都導致了-50錯誤。

爲了能夠更新現有標識,我使用SecItemDelete刪除了現有標識,然後將其與SecItemAdd一起添加。再次令人困惑的是,雖然對SecItemDelete的調用返回了-25300錯誤(errSecItemNotFound),但它可以被忽略,因爲可以在事後添加它(使用SecItemAdd)而不會出錯。

相關問題