简体   繁体   中英

Converting Raw RSA Key value to SecKeyRef Object for Encryption

I have a RSa publicKey value in base64 , how do i convert to SecKeyRef Object without adding to Keychain Can i add a RSA Raw value to Keychain which is not in X509 format ???

thanks in advance

The following code comes from Apple's CryptoExercise example, in SecKeyWrapper.m. It assumes the "publicKey" NSData object is the binary DER-encoded ASN.1 object, not base-64 encoded. So you'll have to get a base-64 decoder and apply it first. You might also want to read this post in the Apple Developer Forums.

- (SecKeyRef)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKey {
    OSStatus sanityCheck = noErr;
    SecKeyRef peerKeyRef = NULL;
    CFTypeRef persistPeer = NULL;

    LOGGING_FACILITY( peerName != nil, @"Peer name parameter is nil." );
    LOGGING_FACILITY( publicKey != nil, @"Public key parameter is nil." );

    NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
    NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];

    [peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
    [peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
    [peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
    [peerPublicKeyAttr setObject:publicKey forKey:(id)kSecValueData];
    [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnPersistentRef];

    sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);

    // The nice thing about persistent references is that you can write their value out to disk and
    // then use them later. I don't do that here but it certainly can make sense for other situations
    // where you don't want to have to keep building up dictionaries of attributes to get a reference.
    // 
    // Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
    // & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef.

    LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecDuplicateItem, @"Problem adding the peer public key to the keychain, OSStatus == %d.", sanityCheck );

    if (persistPeer) {
        peerKeyRef = [self getKeyRefWithPersistentKeyRef:persistPeer];
    } else {
        [peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
        [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnRef];
        // Let's retry a different way.
        sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&peerKeyRef);
    }

    LOGGING_FACILITY1( sanityCheck == noErr && peerKeyRef != NULL, @"Problem acquiring reference to the public key, OSStatus == %d.", sanityCheck );

    [peerTag release];
    [peerPublicKeyAttr release];
    if (persistPeer) CFRelease(persistPeer);
    return peerKeyRef;
}

In case someone comes across this question and is looking for the Cocoa answer:

NSData *privateKeyPEMData = [privateKeyPEM dataUsingEncoding:NSUTF8StringEncoding];
CFArrayRef imported = NULL;
SecKeychainRef importedKeychain = NULL;
OSStatus err = 0;
SecExternalFormat format = kSecFormatOpenSSL;
SecKeyRef privateKey = NULL;

[privateKeyString dataUsingEncoding:NSUTF8StringEncoding];
err = SecItemImport((__bridge CFDataRef)(privateKeyPEMData), (CFStringRef)@"pem", &format, NULL, kNilOptions, kNilOptions, importedKeychain, &imported);
NSLog(@"%@ ERROR: %@", self.class, [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil]);

assert(err == errSecSuccess);
assert(CFArrayGetCount(imported) == 1);
privateKey = (SecKeyRef)CFArrayGetValueAtIndex(imported, 0);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM