我使用这段代码列出所有私钥,并使用Apple的安全框架API获取有关它们的一些信息:

int main(int argc, const char * argv[]) {
    const void *keys[]   = { kSecClass,    kSecReturnRef,   kSecMatchLimit,    kSecAttrKeyClass};
    const void *values[] = { kSecClassKey, kCFBooleanTrue,  kSecMatchLimitAll, kSecAttrKeyClassPrivate};

    CFDictionaryRef searchDict = CFDictionaryCreate(
        NULL,
        keys, values, sizeof(keys) / sizeof(keys[0]),
        NULL, NULL
    );
    checkAlloc(searchDict);

    CFArrayRef items;
    check(SecItemCopyMatching(searchDict, (CFTypeRef *)&items));

    for(int i=0; i<CFArrayGetCount(items); i++) {
        SecKeychainItemRef item = (SecKeychainItemRef) CFArrayGetValueAtIndex(items, i);

        CFShow((CFTypeRef)item);

        SecItemClass cls;
        SecKeychainAttributeList attrs;
        UInt32 dataLen;
        void* data;

        check(SecKeychainItemCopyContent(item, &cls, &attrs, &dataLen, &data));

        printf("Key: %d\n", (int)dataLen);

        check(SecKeychainItemFreeContent(&attrs, data));
    }

    CFRelease(items);
    CFRelease(searchDict);

    return 0;
}

调用SecKeychainItemCopyContentsegfaults,即使我传入的指针都不是无效的。
CFShow打印类似于<SecKey 0x7fb4d9d01420 [0x7fff74790ed0]>的行,因此item应该是aSecKeyRef,但documentation for it表示,如果密钥在密钥链中,则可以使用aSecKeyRef作为aSecKeychainItemRef。但是,我看不到任何函数来查找密钥是否在密钥链中,因此无法验证返回的密钥是否可以这样使用。
我在这里做错什么了?

最佳答案

要复制存储在给定密钥链项中的数据和/或属性,
函数SecKeychainItemCopyContent()的第三个参数是SecKeychainAttributeList *attrList,类型类似,

  struct SecKeychainAttributeList
  {
    UInt32 count;
    SecKeychainAttribute *attr;
  };

对于这个输入/输出参数:在输入时,它是您请求检索的属性列表。输出时,将填充属性。如果不需要检索任何属性,则传递attrList,或者传递需要获取的属性列表。它应该是上述两个传入参数之一。不初始化它可能会导致问题,如分段错误。
所以,请试着这样做,它应该能很好地工作。
SecKeychainAttributeList attrs = {0, NULL};
//...
check(SecKeychainItemCopyContent(item, &cls, &attrs, &dataLen, &data));


//SecKeychainAttributeList attrs ;
//...
check(SecKeychainItemCopyContent(item, &cls, NULL, &dataLen, &data));
printf("Key: %d\n", (int)dataLen);
check(SecKeychainItemFreeContent(NULL, data));

如果需要获取属性列表,示例代码可以如下所示,
 SecKeychainAttributeList xlist;
 SecKeychainAttribute outList[] =
 {
    {kSecAddressItemAttr,},
    {kSecAccountItemAttr,},
    {kSecVolumeItemAttr,},
    {kSecProtocolItemAttr}
 };

 xlist.count = sizeof(outList)/sizeof(outList[0]);
 xlist.attr = outList;

 //...
 err = SecKeychainItemCopyContent (itemRef, nil, &xlist, &len, &outData);
 //...

09-06 12:45