我想使用新的10.7 Security.framework
API导出私有ECDSA密钥,但操作仍然失败,错误代码为-26260:
errSecPassphraseRequired = -25260, /* Passphrase is required for import/export. */
我还希望我生成的密钥不会被添加到钥匙串中,因为它们可以在其他机器上使用,我将自己处理存储。这里的代码不起作用 - 第一次导出成功,但导入的相同密钥数据在没有密码短语的情况下无法再次导出。我没有为此密钥设置密码。我尝试了许多导出类型的组合,包括包装的OpenSSL和PEM装甲,但它似乎没有什么区别。我已经使用OpenSSL执行此操作的代码,但由于它在Lion中已弃用,我想看看新API可以做什么。
// Set up the parameters for 256-bit ECDSA
CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
CFDictionarySetValue(parameters, kSecAttrKeyType, kSecAttrKeyTypeECDSA);
CFDictionarySetValue(parameters, kSecAttrKeySizeInBits, CFSTR("256")); // kSecp256r1
CFDictionarySetValue(parameters, kSecAttrIsPermanent, kCFBooleanFalse);
// Issue #1:
// SecKeyGeneratePair() adds the keys to the keychain, which I don't want to do
// The docs say that kSecAttrIsPermanent should change this behavior
SecKeyRef publicKey, privateKey;
OSStatus result = SecKeyGeneratePair((CFDictionaryRef)parameters, &publicKey, &privateKey);
CFRelease(parameters), parameters = nullptr;
if(noErr == result) {
CFDataRef privateKeyData = nullptr;
result = SecItemExport(privateKey, kSecFormatUnknown, 0, nullptr, &privateKeyData);
if(noErr == result) {
CFShow(privateKeyData);
uint32_t format = kSecFormatUnknown;
uint32_t itemType = kSecItemTypePrivateKey;
CFArrayRef items = nullptr;
result = SecItemImport(privateKeyData, nullptr, &format, &itemType, 0, nullptr, nullptr, &items);
CFRelease(privateKeyData), privateKeyData = nullptr;
CFRelease(privateKey), privateKey = nullptr;
if(noErr == result) {
privateKey = (SecKeyRef)CFRetain(CFArrayGetValueAtIndex(items, 0));
CFRelease(items), items = nullptr;
// Issue #2:
// SecItemExport() fails with -25260
result = SecItemExport(privateKey, kSecFormatUnknown, 0, nullptr, &privateKeyData);
if(noErr == result) {
CFShow(privateKeyData);
CFRelease(privateKeyData), privateKeyData = nullptr;
}
else
printf("SecItemExport error: %d\n", result);
}
else
puts("SecItemImport failed");
}
else
printf("SecItemExport error: %d\n", result);
}
else
printf("SecKeyGeneratePair error: %d\n", result);
以下是样本运行的输出:
<CFData 0x10061b390 [0x7fff79ed3fa0]>{length = 121, capacity = 256, bytes = 0x307702010104209432679e712a4ac156 ... 219ffed31a54aff1}
SecItemExport error: -25260