iOS SecKeyRef to NSData

后端 未结 1 1645
灰色年华
灰色年华 2020-12-05 05:51

I have two keys, public and private, that are both stored in SecKeyRef-variables. For simplicity\'s sake, let\'s start with the public one. What I wanna do is export it to a

相关标签:
1条回答
  • 2020-12-05 06:04
    • use of undeclared identifier 'publicTag'

    The publicTag is just some unique identifier added to the Keychain items. In the CryptoExercise sample project it is defined as

    #define kPublicKeyTag "com.apple.sample.publickey"
    static const uint8_t publicKeyIdentifier[] = kPublicKeyTag;
    NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
    
    • Cast of an indirect pointer to an Objective-C pointer to 'CFTypeRef ' (aka 'const void *') is disallowed with ARC

    This can be solved by using a temporary CFTypeRef variable:

    CFTypeRef result;
    sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPublicKey, &result);
    if (sanityCheck == errSecSuccess) {
        publicKeyBits = CFBridgingRelease(result);
    }
    
    • I do not want to build a query or whatnot to extract the key from the keychain. I have it in a variable and I wish to extract it from there ...

    As far as I know, you have to store the SecKeyRef to the Keychain temporarily. SecItemAdd has the option to return the added item as data. From the documentation:

    To obtain the data of the added item as an object of type CFDataRef, specify the return type key kSecReturnData with a value of kCFBooleanTrue.

    Putting all that together, the following code should do what you want:

    - (NSData *)getPublicKeyBitsFromKey:(SecKeyRef)givenKey {
    
        static const uint8_t publicKeyIdentifier[] = "com.your.company.publickey";
        NSData *publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
    
        OSStatus sanityCheck = noErr;
        NSData * publicKeyBits = nil;
    
        NSMutableDictionary * queryPublicKey = [[NSMutableDictionary alloc] init];
        [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
        [queryPublicKey setObject:publicTag forKey:(__bridge id)kSecAttrApplicationTag];
        [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    
        // Temporarily add key to the Keychain, return as data:
        NSMutableDictionary * attributes = [queryPublicKey mutableCopy];
        [attributes setObject:(__bridge id)givenKey forKey:(__bridge id)kSecValueRef];
        [attributes setObject:@YES forKey:(__bridge id)kSecReturnData];
        CFTypeRef result;
        sanityCheck = SecItemAdd((__bridge CFDictionaryRef) attributes, &result);
        if (sanityCheck == errSecSuccess) {
            publicKeyBits = CFBridgingRelease(result);
    
            // Remove from Keychain again:
            (void)SecItemDelete((__bridge CFDictionaryRef) queryPublicKey);
        }
    
        return publicKeyBits;
    }
    

    I hope that this works, I cannot test it at the moment.

    • Follow-up: How can I export a private key to NSData, since I've read several time that the function I'm trying to work with only works for public keys.

    I don't know.

    0 讨论(0)
提交回复
热议问题