Translate just 4 lines of code from objective c to swift (Pointers)

I have been stuck since two days translating a piece of code from Objective-C to Swift:

CFArrayRef keyref = NULL;
CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict,      kSecImportItemIdentity);

Yes, that’s all! I simply can’t satisfy the compiler with those pointers.
Please help 🙂

  • Xcode Set Compatible Devices
  • Install old cocoapods?
  • Xcode 6 with Swift super slow typing and autocompletion
  • how to provide only one view with landscape for MPMoviePlayerController in IOS6
  • Table view cell expanding in IOS 7
  • How to identify timezone from longitude and latitude in iOS
  • This is the whole objective c code to translate:

    // Read .p12 file
    NSString *path = [[NSBundle mainBundle] pathForResource:@"SSLKeyStoreClient" ofType:@"p12"];
    NSData *pkcs12data = [[NSData alloc] initWithContentsOfFile:path];
    
    // Import .p12 data
    CFArrayRef keyref = NULL;
    OSStatus sanityChesk = SecPKCS12Import((__bridge CFDataRef)pkcs12data,
                                           (__bridge CFDictionaryRef)[NSDictionary
                                                                      dictionaryWithObject:@"wed-zzz"
                                                                      forKey:(__bridge id)kSecImportExportPassphrase],
                                           &keyref);
    if (sanityChesk != noErr) {
        NSLog(@"Error while importing pkcs12 [%d]", (int)sanityChesk);
    } else
        NSLog(@"Success opening p12 certificate.");
    
    // Identity
    CFDictionaryRef identityDict = CFArrayGetValueAtIndex(keyref, 0);
    SecIdentityRef identityRef = (SecIdentityRef)CFDictionaryGetValue(identityDict,
                                                                      kSecImportItemIdentity);
    
    // Cert
    SecCertificateRef cert = NULL;
    OSStatus status = SecIdentityCopyCertificate(identityRef, &cert);
    if (status)
        NSLog(@"SecIdentityCopyCertificate failed.");
    
    // the certificates array, containing the identity then the root certificate
    NSArray *myCerts = [[NSArray alloc] initWithObjects:(__bridge id)identityRef, (__bridge id)cert, nil];
    
    NSMutableDictionary *SSLOptions;
    [SSLOptions setObject:[NSNumber numberWithBool:YES] forKey:(NSString *)kCFStreamSSLAllowsExpiredRoots];
    
    NSDictionary *settings = [[NSDictionary alloc] initWithObjectsAndKeys:
                              [NSNumber numberWithBool:YES], kCFStreamSSLAllowsExpiredCertificates,
                              [NSNumber numberWithBool:YES], kCFStreamSSLAllowsAnyRoot,
                              [NSNumber numberWithBool:NO], kCFStreamSSLValidatesCertificateChain,
                              kCFNull,kCFStreamSSLPeerName,
                              myCerts,kCFStreamSSLCertificates,
                              nil];
    
    
    CFReadStreamSetProperty((CFReadStreamRef)self.inputStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
    CFWriteStreamSetProperty((CFWriteStreamRef)self.outputStream, kCFStreamPropertySSLSettings, (CFTypeRef)settings);
    

    And this is what i got so far:

    // Read .p12 file
    var path = NSBundle.mainBundle().pathForResource("SSLKeyStoreClient", ofType: "p12")
    var pkcs12data: NSData = NSData.dataWithContentsOfFile(path, options: nil, error: nil)
    
    // Import .p12 data
    var keyref: Unmanaged<CFArray>?
    
    
    var optionDict: NSMutableDictionary = NSMutableDictionary()
    optionDict.setValue("wed-zzz", forKey: kSecImportExportPassphrase!.takeRetainedValue())
    
    var sanityChesk = SecPKCS12Import(pkcs12data,optionDict,&keyref)
    if sanityChesk != 0{ //noErr
       println("Error while importing pkcs12 \(sanityChesk)")
    } else {
       println("Success opening p12 certificate.")
    }
    
    
    // Identity
    var key = keyref!
    var identityDict: CFDictionary = CFArrayGetValueAtIndex(keyref, 0)
    var identityRef:COpaquePointer = CFDictionaryGetValue(identityDict,nil)
    
    
    // Cert
    var cert: Unmanaged<SecCertificate>?
    var status: OSStatus  = SecIdentityCopyCertificate(identityRef, &cert)
    if status == 0{
        println("SecIdentityCopyCertificate failed.")
    }
    
    // the certificates array, containing the identity then the root certificate
    var sslOptions = Dictionary<NSObject, NSObject>()
    
    sslOptions[kCFStreamSSLAllowsExpiredRoots] = NSNumber.numberWithBool(true)
    
    var settings = Dictionary<NSObject, NSObject>()
    settings[kCFStreamSSLAllowsExpiredCertificates] = NSNumber.numberWithBool(true)
    settings[kCFStreamSSLAllowsAnyRoot] = NSNumber.numberWithBool(true)
    settings[kCFStreamSSLValidatesCertificateChain] = NSNumber.numberWithBool(false)
    settings[kCFStreamSSLPeerName] = kCFNull
    //settings[kCFStreamSSLCertificates] = myCerts
    
    
    
        CFReadStreamSetProperty(self.inputStream, kCFStreamPropertySSLSettings, settings)
        CFReadStreamSetProperty(self.inputStream, kCFStreamPropertySSLSettings, settings)
    

    The Problem starts at:

    var identityDict: CFDictionary = CFArrayGetValueAtIndex(keyref, 0)
    

    Error: “unmanaged CFArray not convertible to CFArray”.

    This is my best try so far.

    Solutions Collect From Internet About “Translate just 4 lines of code from objective c to swift (Pointers)”

    Presumably the first line is a placeholder for an actual array? If you’re actually working with a NULL array pointer, the rest of your code does nothing.

    Assuming you’re starting from a real CFArrayRef, you can take advantage of bridging: CoreFoundation types are automatically treated like Swift objects, so you don’t need to work with CFArrayRef and CFDictionaryRef pointers. The same goes for any other C API that uses the CF type system, so it should also apply to SecIdentity.

    There seems to be some weirdness with automatic bridging of CF collections — you can implicitly bridge a CFArray to an NSArray and an NSArray to a Swift Array<T>, you can’t just subscript a CFArray.

    So your conversion looks something like this (wrapped in a function that handles your assumed array):

    func getIdentity(keychainArray: NSArray) -> SecIdentity? {
        let dict = keychainArray[0] as Dictionary<String,AnyObject>
        let key = kSecImportItemIdentity.takeRetainedValue()
        return dict[key] as SecIdentity?
    }
    

    If you have a CFArray you can pass it to this function and it’ll automatically bridge/cast to NSArray, which then automatically casts to a Swift array for subscripting. Treat item 0 as a Swift dictionary, and you can subscript the dictionary to get the identity out. For the key, you’ll need to pull it out of an Unmanaged<CFString> because the Security framework isn’t set up for implicit bridging of that constant’s declaration.

    I’ve left this function returning an optional, since I don’t know wether the array+dictionary you’re passing in actually contains an identity. If you’re sure it does, you could take out the two question marks.

    (This compiles in playground, but I don’t have an array containing a dictionary containing an identity handy for testing with, so caveat emptor.)