On Feb 8, 2013, at 1:31 PM, Damien Cooke <dam...@smartphonedev.com> wrote:

> I am trying to put a public key into the ios keychain so I can get a 
> SecKeyRef to use to verify a signature.

Oh dear. Any time I have to deal with the iOS keychain APIs I get either 
enraged or sick to my stomach or both. Seriously.

> So I strip the begin and end markers plus remove all the \n (is this correct?)

And also base64-decode it, right? It definitely won’t work unless you do that 
too.
(This looks like a PEM-encoded key; to make sure, you could look up the docs on 
that format. But I think you’ve basically got it right.)

> The SecItemAdd succeeds but I can never get it out again as 
> SecItemCopyMatching always returns null in the ref pointer but returns 
> errSecSuccess so I am really confused.

Yeah, this is a good example of where my rage/ulcer reactions come from. The 
SecItem API is one of the worst things ever: it’s incredibly vague and 
under-documented, and just does not seem to behave in reasonable ways or return 
informative errors.

Here’s some code I have for this purpose. It’s been about a year since I’ve 
worked with it so I’m no longer clear on all the details.
One thing to note is that the app this is for is using the SHA-1 digest of the 
key as the “application tag” property for looking up the key afterwards, thus 
the usage of the digest in the parameters to SecItemAdd.
Also, the weird stuff about converting the persistent ref to a regular one is 
to work around a bug(?) in the keychain code, where you apparently have to 
request a persistent ref when adding a new item, but then can’t work with that 
ref unless you convert it to a regular one.
This code is the boiled-down end product of literally about ten cumulative 
hours of frustration and experimentation, so it may be messier than it needs to 
be. If someone knows how to do this more elegantly, I’m all ears.

—Jens

PS: The apple-cdsa list is the appropriate one for talking about this stuff, 
although I’ve noticed that the Apple engineers there never seem to answer 
detailed questions about the keychain APIs :-p

    SHA1Digest digest = ComputeSHA1(keyData);  // this is a fn of mine that 
just calls CommonCrypto
    NSData* digestData = [NSData dataWithBytes: &digest length: sizeof(digest)];
    
    NSMutableDictionary* attrs = [NSMutableDictionary 
dictionaryWithObjectsAndKeys:
                                  (id)kSecClassKey,        (id)kSecClass,
                                  (id)kSecAttrKeyTypeRSA,  (id)kSecAttrKeyType,
                                  (id)kSecAttrKeyClassPublic, 
(id)kSecAttrKeyClass,
                                  digestData,              
(id)kSecAttrApplicationTag, //????
                                  digestData,              
(id)kSecAttrApplicationLabel,
                                  keyData,                 (id)kSecValueData,
                                  (id)kCFBooleanTrue,      
(id)kSecReturnPersistentRef,
                                  nil];
    CFTypeRef keyRef = NULL;
    OSStatus err = SecItemAdd((CFDictionaryRef)attrs, &keyRef);
    if (err) {
        if (err != errSecDuplicateItem)
            return err;
        // Already have a key with this digest, so look it up to get its ref:
        [attrs removeObjectForKey: (id)kSecValueData];
        [attrs setObject: digestData forKey: (id)kSecAttrApplicationLabel];//??
        [attrs removeObjectForKey: (id)kSecReturnPersistentRef];
        [attrs setObject: (id)kCFBooleanTrue forKey: (id)kSecReturnRef];
        return SecItemCopyMatching((CFDictionaryRef)attrs, 
(CFTypeRef*)outPublicKey);
    }
    
    // Added it -- now convert the persistent ref to a regular one:
    NSMutableDictionary* query = [NSMutableDictionary 
dictionaryWithObjectsAndKeys:
                                  (id)kSecClassKey,        (id)kSecClass,
                                  (id)kSecAttrKeyTypeRSA,  (id)kSecAttrKeyType,
                                  digestData,              
(id)kSecAttrApplicationTag, //????
                                  //(id)keyRef, (id)kSecValuePersistentRef,
                                  (id)kCFBooleanTrue, (id)kSecReturnRef,
                                  nil];
    //CFRelease(keyRef);
    return SecItemCopyMatching((CFDictionaryRef)query, 
(CFTypeRef*)outPublicKey);

_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to