将对称密钥 SecKeyRef 项导出为 CFDataRef

发布于 2024-12-04 10:30:13 字数 2770 浏览 2 评论 0原文

我在将对称密钥从 SecKeyRef 导出到 CFDataRef 进行包装或存储或仅与其他 Cocoa 代码一起使用时遇到一些麻烦。

我有以下代码:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    SecKeyRef sessionKey = [self generateRandomSymmetricKey];
    CFDataRef sessionKeyData = [self exportSymmetricKeyAsCFData:sessionKey];
}

- (SecKeyRef)generateRandomSymmetricKey {
    SecKeyRef cryptoKey = NULL;
    CFErrorRef error = NULL;

    // Create the dictionary of key parameters
    CFMutableDictionaryRef parameters = (__bridge CFMutableDictionaryRef)[NSMutableDictionary dictionaryWithObjectsAndKeys:kSecAttrKeyTypeAES, kSecAttrKeyType, (__bridge CFNumberRef)[NSNumber numberWithInt:256], kSecAttrKeySizeInBits, nil];

    // Generate a symmetric key based on the parameters
    cryptoKey = SecKeyGenerateSymmetric(parameters, &error);

    return cryptoKey;
}

- (CFDataRef)exportSymmetricKeyAsCFData:(SecKeyRef)cryptoKey {  
    // Create and populate the parameters object with a basic set of values
    SecItemImportExportKeyParameters params;

    params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
    params.flags = 0;
    params.passphrase = NULL;
    params.alertTitle = NULL;
    params.alertPrompt = NULL;
    params.accessRef = NULL;
    // These two values are for import
    params.keyUsage = NULL;
    params.keyAttributes = NULL;

    // Create and populate the key usage array
    CFMutableArrayRef keyUsage = (__bridge CFMutableArrayRef)[NSMutableArray arrayWithObjects:kSecAttrCanEncrypt, kSecAttrCanDecrypt, nil];

    // Create and populate the key attributes array
    CFMutableArrayRef keyAttributes = (__bridge CFMutableArrayRef)[NSMutableArray array];

    // Set the keyUsage and keyAttributes in the params object
    params.keyUsage = keyUsage;
    params.keyAttributes = keyAttributes;

    // Set the external format and flag values appropriately
    SecExternalFormat externalFormat = kSecFormatUnknown; // Should result in the default appropriate external format for the given key.
    int flags = 0;

    // Export the CFData Key
    CFDataRef keyData = NULL;
    CFShow(cryptoKey);
    OSStatus oserr = SecItemExport(cryptoKey, externalFormat, flags, &params, &keyData);
    if (oserr) {
        fprintf(stderr, "SecItemExport failed (oserr= %d)\n", oserr);
        exit(-1);
    }

    NSLog(@"Exported Symmetric Key Data: %@", [(__bridge NSData *)keyData bytes]);
    return keyData;
}

但我最终在日志中得到的是:

SecItemExport 失败(oserr= -25316)

“oserr= -25316” 在 SecBase.h 中定义为:

errSecDataNotAvailable = -25316, /* 无法检索此项的内容。 */

我最初认为该错误意味着 SecKeyRef 提前发布或类似的情况,但正如您从日志中看到的那样,SecKey 报告本身很好。

关于我在这里缺少什么或做错了什么有什么想法吗?谢谢!

I am having some trouble with getting a symmetric key exported from a SecKeyRef to a CFDataRef for wrapping or storing,or simply for use with other Cocoa code.

I have the following code:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
    SecKeyRef sessionKey = [self generateRandomSymmetricKey];
    CFDataRef sessionKeyData = [self exportSymmetricKeyAsCFData:sessionKey];
}

- (SecKeyRef)generateRandomSymmetricKey {
    SecKeyRef cryptoKey = NULL;
    CFErrorRef error = NULL;

    // Create the dictionary of key parameters
    CFMutableDictionaryRef parameters = (__bridge CFMutableDictionaryRef)[NSMutableDictionary dictionaryWithObjectsAndKeys:kSecAttrKeyTypeAES, kSecAttrKeyType, (__bridge CFNumberRef)[NSNumber numberWithInt:256], kSecAttrKeySizeInBits, nil];

    // Generate a symmetric key based on the parameters
    cryptoKey = SecKeyGenerateSymmetric(parameters, &error);

    return cryptoKey;
}

- (CFDataRef)exportSymmetricKeyAsCFData:(SecKeyRef)cryptoKey {  
    // Create and populate the parameters object with a basic set of values
    SecItemImportExportKeyParameters params;

    params.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION;
    params.flags = 0;
    params.passphrase = NULL;
    params.alertTitle = NULL;
    params.alertPrompt = NULL;
    params.accessRef = NULL;
    // These two values are for import
    params.keyUsage = NULL;
    params.keyAttributes = NULL;

    // Create and populate the key usage array
    CFMutableArrayRef keyUsage = (__bridge CFMutableArrayRef)[NSMutableArray arrayWithObjects:kSecAttrCanEncrypt, kSecAttrCanDecrypt, nil];

    // Create and populate the key attributes array
    CFMutableArrayRef keyAttributes = (__bridge CFMutableArrayRef)[NSMutableArray array];

    // Set the keyUsage and keyAttributes in the params object
    params.keyUsage = keyUsage;
    params.keyAttributes = keyAttributes;

    // Set the external format and flag values appropriately
    SecExternalFormat externalFormat = kSecFormatUnknown; // Should result in the default appropriate external format for the given key.
    int flags = 0;

    // Export the CFData Key
    CFDataRef keyData = NULL;
    CFShow(cryptoKey);
    OSStatus oserr = SecItemExport(cryptoKey, externalFormat, flags, ¶ms, &keyData);
    if (oserr) {
        fprintf(stderr, "SecItemExport failed (oserr= %d)\n", oserr);
        exit(-1);
    }

    NSLog(@"Exported Symmetric Key Data: %@", [(__bridge NSData *)keyData bytes]);
    return keyData;
}

But all I end up with in my logs is:

SecItemExport failed (oserr= -25316)

"oserr= -25316" is defined in SecBase.h as:

errSecDataNotAvailable = -25316, /* The contents of this item cannot be retrieved. */

I would have originally thought that error to mean that the SecKeyRef was released early or something like that, but as you can see from the log, the SecKey is reporting itself just fine.

Any ideas as to what I'm missing or doing wrong here? Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

少女的英雄梦 2024-12-11 10:30:13

与 Apple 交谈后,发现此问题是由“Extractable”属性设置为 NO 引起的,但无法使用 SecKeyGenerateSymmetric() 设置该参数。

已提交错误,但本质上是在该错误得到解决之前,解决方案是使用已弃用的方法 SecKeyGenerate()

而不是上面的 - (SecKeyRef)generateRandomSymmetricKey 方法,请使用以下方法:

- (SecKeyRef)generateRandomSymmetricKey {
    SecKeyRef symmetricKey;

    OSStatus oserr = SecKeyGenerate(NULL, CSSM_ALGID_AES, 256, 0, (CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT), CSSM_KEYATTR_EXTRACTABLE, NULL, &symmetricKey);
    if (oserr) {
        NSLog(@"SecKeyGenerate failed: %@", (__bridge NSString *)SecCopyErrorMessageString(oserr, NULL));
        exit(-1);
    }

    return symmetricKey;
}

我希望这对某人有帮助。

After talking with Apple, it turns out this issue is caused by the "Extractable" attribute being set to NO, but having no way to set that parameter with SecKeyGenerateSymmetric()

A bug has been filed, but essentially until that bug is resolved the solution is to use the depreciated method SecKeyGenerate().

Instead of the - (SecKeyRef)generateRandomSymmetricKey method above use this:

- (SecKeyRef)generateRandomSymmetricKey {
    SecKeyRef symmetricKey;

    OSStatus oserr = SecKeyGenerate(NULL, CSSM_ALGID_AES, 256, 0, (CSSM_KEYUSE_DECRYPT | CSSM_KEYUSE_ENCRYPT), CSSM_KEYATTR_EXTRACTABLE, NULL, &symmetricKey);
    if (oserr) {
        NSLog(@"SecKeyGenerate failed: %@", (__bridge NSString *)SecCopyErrorMessageString(oserr, NULL));
        exit(-1);
    }

    return symmetricKey;
}

I hope this helps someone.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文