2013-10-24 93 views
3

我試圖通過鑰匙串API從鑰匙串中刪除配對私鑰的證書。我可以輕鬆刪除證書,但私鑰總是被留下。我怎樣才能從鑰匙串中刪除它? 我已經嘗試了幾種方法,但即使使用SecKeyRef,一旦我運行SecItemDelete(例如),該函數將返回errSecSuccess的狀態,但密鑰仍然存在於鑰匙串中!以編程方式從鑰匙串中刪除私鑰(與證書匹配)

任何幫助,非常感謝,如果有任何示例代碼,請發佈它。 Errrrr!這是如此令人沮喪...

謝謝..

回答

0

嗯,這個問題的答案是有點棘手.... 顯然,有關於這件事情的蘋果已知的bug,沒有已知的解決方法(這是取自蘋果的DTS響應)。

如果有一個ACL限制對其的訪問並允許一個和一個應用程序訪問密鑰,則可以刪除私鑰。 所以,從理論上講,可以更改訪問對象並限制ACL列表,然後刪除它。

但是....不幸的是,試圖操縱身份的訪問對象有相同的ACL時手動更改它通過鑰匙串訪問不表現爲很好的...

如果你設法萬一限制那麼剩下的是很容易的:

因此,這裏是以防萬一有人代碼段發現它有用:

OSStatus status  = errSecSuccess; 
CFTypeRef identityRef = NULL; 
CFStringRef certLabel = NULL; 

const char *certLabelString = "Some string identifying your certificate"; 
certLabel = CFStringCreateWithCString(NULL, certLabelString, kCFStringEncodingUTF8); 

const void *keys[] = { kSecClass, kSecAttrLabel, kSecReturnRef }; 
const void *values[] = { kSecClassIdentity, certLabel, kCFBooleanTrue }; 
CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, 3, NULL, NULL); 

// First we extract the identity out of the keychain 
status = SecItemCopyMatching(query, &identityRef); 
if (status != errSecSuccess) 
{ 
    s_log(SecCopyErrorMessageString(status, NULL)); 
    CFRelease(certLabel); 
    CFRelease(query); 
    if (identityRef) 
     CFRelease(identityRef); 

    return -1; 
} 

CFRelease(certLabel); 
CFRelease(query); 

// We have obtained the identity so we can delete it 
CFArrayRef itemList = CFArrayCreate(NULL, &identityRef, 1, NULL); 
const void *keys2[] = { kSecClass, kSecMatchItemList, kSecMatchLimit }; 
const void *values2[] = { kSecClassIdentity, itemList, kSecMatchLimitAll }; 

CFDictionaryRef dict = CFDictionaryCreate(NULL, keys2, values2, 3, NULL, NULL); 
status = SecItemDelete(dict); 

if (status != errSecSuccess) { 
    s_log(SecCopyErrorMessageString(status, NULL)); 
    CFRelease(dict); 
    CFRelease(itemList); 
    CFRelease(identityRef); 
    return -2; 
}