2

我有一些麻煩,獲取從SecKeyRef導出到CFDataRef包裝或存儲,或只是爲了與其他Cocoa代碼一起使用的對稱密鑰。導出一個對稱密鑰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報告自己就好。

有關我在這裏失蹤或做錯的任何想法?謝謝!

回答

4

與蘋果交談後,事實證明這個問題是由「可開採」屬性被設置爲NO,但沒有辦法設置的bug已經提交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; 
} 

我希望這可以幫助別人。