Экспорт элемента SecKeyRef с симметричным ключом в виде CFDataRef - PullRequest
2 голосов
/ 15 сентября 2011

У меня возникли проблемы с получением симметричного ключа, экспортированного из SecKeyRef в CFDataRef для упаковки или хранения, или просто для использования с другим кодом Какао.

У меня есть следующий код:

- (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 сообщает о себе очень хорошо.

Есть идеи о том, что я здесь упускаю или делаю неправильно?Спасибо!

1 Ответ

4 голосов
/ 07 октября 2011

После разговора с Apple выясняется, что эта проблема вызвана тем, что для атрибута «Извлекаемый» задано значение «НЕТ», но невозможно установить этот параметр с помощью 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;
}

Я надеюсь, что это кому-то поможет.

...