Apple的
documentation for OS X谈到使用SecItemImport来获取一个SecKeyRef.函数签名如下所示:
OSStatus SecItemImport ( CFDataRef importedData,CFStringRef fileNameOrExtension,SecExternalFormat *inputFormat,SecExternalItemType *itemType,SecItemImportExportFlags flags,const SecItemImportExportKeyParameters *keyParams,SecKeychainRef importKeychain,CFArrayRef *outItems );
以下代码将尝试加载包含单个RSA密钥的PKCS12字节数组:
#include <Security/Security.h> #include <Security/SecKey.h> #include <CoreFoundation/CoreFoundation.h> int main(void) { CFArrayRef array = NULL; SecItemImportExportKeyParameters params; SecExternalItemType itemType = kSecItemTypeUnknown; SecExternalFormat format = kSecFormatUnknown; params.flags = kSecKeyNoAccessControl; UInt8 bytes[] = { 0x30,0x82,0x2,0x1e,0x1,0x3,0x30,0xe8,0x6,0x9,0x2a,0x86,0x48,0xf7,0xd,0x7,0xa0,0xd9,0x4,0xd5,0xd1,0xcd,0xbe,0xba,0xb6,0xb2,0xb,0xc,0xa,0x1c,0xe,0x8,0x8f,0x14,0x15,0x85,0x8e,0x64,0x6c,0x0,0x60,0x44,0x55,0x7e,0xa3,0xce,0x63,0xb0,0x83,0xf6,0x34,0xb8,0x88,0xe3,0x6e,0xbf,0xcb,0xe7,0x4f,0x57,0xde,0xaa,0x28,0x38,0x6f,0xc0,0xd2,0xcc,0xc9,0x95,0x1b,0x69,0x2c,0x7b,0x78,0xdf,0x77,0xd7,0xb3,0xe6,0x3f,0xe2,0x68,0x2e,0x50,0x97,0x16,0x1d,0x7a,0x26,0x80,0xf5,0xe5,0x45,0xed,0x99,0x87,0x7c,0x19,0xaf,0x41,0xf4,0xdb,0x2b,0x42,0xac,0x9c,0x1f,0x5c,0x32,0x3a,0xe4,0xc2,0x18,0x9b,0x5f,0xa4,0xf1,0xec,0xe0,0xd3,0xc4,0x7d,0x25,0xd4,0x8b,0x6d,0xa6,0x8d,0xf3,0x13,0xdd,0x11,0x6b,0xda,0x12,0x75,0xfa,0xa1,0x92,0x54,0x81,0x9a,0xa8,0x4b,0x21,0x8c,0xc7,0x3e,0x59,0x5b,0xad,0x9e,0x4e,0xee,0x3c,0x36,0x5e,0x17,0x51,0xb1,0x43,0x89,0x98,0xb7,0x23,0x58,0xa7,0xf9,0xf,0x61,0xa9,0x72,0x52,0x8a,0xbc,0x46,0x2f,0xb5,0xdc,0x93,0x90,0x74,0x66,0xd6,0x40,0x53,0x62,0x5a,0x10,0x7f,0x29,0x4d,0x70,0x96,0xef,0xb4,0x4c,0x20,0x5d,0xff,0x9d,0x6a,0x9f,0x3b,0x73,0x31,0x65,0x2d,0x5,0x1a,0x91,0x35,0xfc,0xcf,0x24,0xc6,0xfe,0xbb,0xe1,0x97 }; FILE* file = fopen( "test.p12","wb" ); fwrite( bytes,sizeof(UInt8),sizeof(bytes)/sizeof(UInt8),file ); params.passphrase = CFStringCreateWithCString(kcfAllocatorDefault,"pass",kcfStringEncodingASCII); CFDataRef dataref = CFDataCreate(kcfAllocatorDefault,bytes,sizeof(bytes)/sizeof(bytes[0])); OSStatus res = SecItemImport(dataref,CFSTR(".p12"),&format,&itemType,¶ms,NULL,&array); printf("response: %d\n",res); printf("format: %d\n",format); printf("itemType: %d\n",itemType); printf("count: %ld\n",CFArrayGetCount(array)); }
要编译上面你可以使用clang filename.c -framework安全框架CoreFoundation.
此代码不返回错误(OSStatus 0),但无法使用解析的SecKeyRef填充数组.我已经尝试了很多不同的标志,但是没有能够得到它来返回所需的数据.有谁知道我在做错什么?
解决方法
这真的看起来像一个钥匙串bug.那并不令人震惊钥匙扣有很多小角落处理不好.我会打开一个雷达(bugreport.apple.com).一些附加说明:
PKCS12通常用于存储证书以及私钥.你只是导入一个裸私钥.我认为这是没有很好的测试,虽然它声称被支持:
Note: When importing a PKCS12 blob,typically one SecIdentityRef object and zero or more additional SecCertificateRef objects are returned in outItems. No SecKeyRef objects are returned unless a key is found in the incoming blob that does not have a matching certificate.
如果有证书参与,我会很好奇.
我已经用钥匙串(使用SecKeychainCreate创建)尝试了这个代码.所产生的钥匙串可由Keychain Access读取,并包含私钥,因此导入工作正常.
我尝试使用与SecPKCS12Import相同的代码,但返回相同的结果.例如,我确保memset()参数结构,你的代码应该是,但不是.
作为一个不相关的一点,你泄露密码.你应该使用CFSTR()来传递常量字符串.