I have a DER encoded digital certificate that comes from outside a keychain. I am trying to search the keychain for a matching private key.
I am able to parse the DER certificate and show all the values as follows:
CFErrorRef error = NULL;
CFDataRef data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, cert->der, cert->len, kCFAllocatorNull);
SecCertificateRef certref = SecCertificateCreateWithData(kCFAllocatorDefault, data);
CFDictionaryRef values = SecCertificateCopyValues(certref, NULL, &error);
CFShow(values);
I am able to search for keys in the keychain as follows:
CFTypeRef keys = NULL;
CFIndex count;
CFIndex i;
CFStringRef dictkeys[] = {
kSecClass,
kSecMatchLimit,
kSecReturnRef,
kSecReturnAttributes
};
CFTypeRef dictvalues[] = {
kSecClassKey,
kSecMatchLimitAll,
kCFBooleanTrue,
kCFBooleanTrue
};
CFDictionaryRef query = CFDictionaryCreate(
NULL,
(const void **) dictkeys,
dictvalues,
sizeof(dictkeys) / sizeof(dictkeys[0]),
&kCFTypeDictionaryKeyCallBacks,
&kCFTypeDictionaryValueCallBacks
);
OSStatus err = SecItemCopyMatching(query, &keys);
Where I am stuck is how to join the two together.
What value from the certificate should I be extracting to allow a lookup for a link to the private key?
What parameter do I pass into SecItemCopyMatching to search for a matching private key?
The best answer to your original question depends on the platform:
-
On macOS you have the handy-dandy
SecIdentityCreateWithCertificate
call, which does exactly what you want. -
On other platforms the only good option is to rely on the matching algorithm, based on
kSecAttrApplicationLabel
andkSecAttrPublicKeyHash
, that’s described in SecItem attributes for keys.
In theory I could emulate this code with
SecCertificateCopyKey
andSecSHA1DigestCreate
, but this would then break as soon as Apple used a digest other than SHA1.
I wouldn’t worry about this algorithm breaking. Given that these attributes are baked into a bazillion keychains scattered across a bazillion devices, it’d be hard for Apple to change the algorithm.
As far as implementing this algorithm is concerned, be aware that SecSHA1DigestCreate
is not public API. The droids you’re looking for here are:
-
SecCertificateCopyKey
-
SecKeyCopyExternalRepresentation
-
Common Crypto’s
CC_SHA1
(Folks using Swift can take advantage o Apple CryptoKit’s much nicerInsecure.SHA1.hash(_:)
.)
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"