SecKeychainItemCopyContents 在私钥上出现段错误
SecKeychainItemCopyContents is segfaulting on private keys
我正在使用此代码列出所有私钥并获取有关它们的一些信息,使用 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;
}
对 SecKeychainItemCopyContent
段错误的调用,即使我传递的 none 个指针无效。
CFShow
打印类似于 <SecKey 0x7fb4d9d01420 [0x7fff74790ed0]>
的行,因此 item
应该是 SecKeyRef
,但是 documentation for it 表示可以使用SecKeyRef
作为 SecKeychainItemRef
如果钥匙在钥匙串中。但是,我没有看到任何函数来查找密钥是否在钥匙串中,因此我无法验证返回的密钥是否可以这样使用。
我做错了什么?
要复制存储在给定钥匙串项中的数据 and/or 属性,
函数 SecKeychainItemCopyContent()
的第三个参数是 SecKeychainAttributeList *attrList
类型如
struct SecKeychainAttributeList
{
UInt32 count;
SecKeychainAttribute *attr;
};
对于此 IN/OUT 参数 attrList
:在输入时,它是您请求检索的属性列表。在输出时,属性被填充。如果不需要检索任何属性,则传递 NULL
,或者传递您需要获取的属性列表。它应该是这两个提到的传递参数中的任何一个。让它未初始化可能会导致问题,例如段错误。
所以,请像这样尝试,它应该会很好。
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);
//...
显然,SecKeychainAttributeList
参数不仅仅是一个输出。它也是一个包含要获取的属性的输入。
SecKeychainAttributeList
取消引用未初始化的 attrs->attr
指针并崩溃。初始化指向 NULL
的指针可以解决问题。
我正在使用此代码列出所有私钥并获取有关它们的一些信息,使用 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;
}
对 SecKeychainItemCopyContent
段错误的调用,即使我传递的 none 个指针无效。
CFShow
打印类似于 <SecKey 0x7fb4d9d01420 [0x7fff74790ed0]>
的行,因此 item
应该是 SecKeyRef
,但是 documentation for it 表示可以使用SecKeyRef
作为 SecKeychainItemRef
如果钥匙在钥匙串中。但是,我没有看到任何函数来查找密钥是否在钥匙串中,因此我无法验证返回的密钥是否可以这样使用。
我做错了什么?
要复制存储在给定钥匙串项中的数据 and/or 属性,
函数 SecKeychainItemCopyContent()
的第三个参数是 SecKeychainAttributeList *attrList
类型如
struct SecKeychainAttributeList
{
UInt32 count;
SecKeychainAttribute *attr;
};
对于此 IN/OUT 参数 attrList
:在输入时,它是您请求检索的属性列表。在输出时,属性被填充。如果不需要检索任何属性,则传递 NULL
,或者传递您需要获取的属性列表。它应该是这两个提到的传递参数中的任何一个。让它未初始化可能会导致问题,例如段错误。
所以,请像这样尝试,它应该会很好。
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);
//...
显然,SecKeychainAttributeList
参数不仅仅是一个输出。它也是一个包含要获取的属性的输入。
SecKeychainAttributeList
取消引用未初始化的 attrs->attr
指针并崩溃。初始化指向 NULL
的指针可以解决问题。