I am trying to read public keys from the keychain APIs in C code, and have got very close. I am however receiving a message asking me to unlock the keychain to access the private key - over and over again, once for each key.
How do I extract public keys (not private keys) from the keychain without triggering a terrible user experience?
Unlocking the keychain once is fine.
CFTypeRef keys = NULL;
CFIndex count;
CFIndex i;
CFStringRef dictkeys[] = {
kSecClass,
kSecMatchLimit,
kSecReturnRef
};
CFTypeRef dictvalues[] = {
kSecClassKey,
kSecMatchLimitAll,
kCFBooleanTrue
};
CFDictionaryRef query = CFDictionaryCreate(
NULL,
(const void **) dictkeys,
dictvalues,
sizeof(dictkeys) / sizeof(dictkeys[0]),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
);
OSStatus err = SecItemCopyMatching(query, &keys);
if (err != errSecSuccess) {
[snip]
}
// we see our keys here no problem
CFShow(keys);
count = CFArrayGetCount(keys);
for (i = 0; i < count; i++) {
CFErrorRef err = NULL;
SecKeyRef kref = (SecKeyRef) CFArrayGetValueAtIndex(keys, i);
// on this line we're asked to unlock the keychain, over and over
SecKeyRef pref = SecKeyCopyPublicKey(kref);
if (!pref) {
continue;
}
CFDataRef der = SecKeyCopyExternalRepresentation(pref, &err);
[snip]
}
CFRelease(keys);