4

我想使用新的 10.7 Security.frameworkAPI 导出私有 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
4

0 回答 0