Translate just 4 lines of code from objective s to fast (pointers)

I've 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 just can't satisfy the compiler with these pointers. Please, help: -)

This is all objective c-code for translation:

 // 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 with:

 var identityDict: CFDictionary = CFArrayGetValueAtIndex(keyref, 0) 

Error: "Unmanaged CFArray does not convert to CFArray."

This is my best attempt so far.

+6
source share
1 answer

Presumably the first line is a placeholder for the actual array? If you really work with a NULL array pointer, the rest of your code does nothing.

Assuming you start with a real CFArrayRef , you can use a bridge: CoreFoundation types are automatically processed as Swift objects, so you don't need to work with CFArrayRef and CFDictionaryRef . The same applies to any other C API that uses the CF type system, so it should also apply to SecIdentity .

There seems to be some kind of weirdness with auto-intersecting CF collections - you can implicitly translate CFArray to NSArray and NSArray to Swift Array<T> , you can't just index a CFArray .

So, your conversion looks something like this (wrapped in a function that processes your intended 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 CFArray , you can pass it to this function and it will automatically go to / t 26 on NSArray , which will then automatically add to the Swift array for signature. Treat element 0 as a Swift dictionary, and you can index the dictionary to get an identifier. For the key, you need to pull it out of the Unmanaged<CFString> because the security structure is not configured to implicitly bridge this constant declaration.

I left this function, returning optional, since I do not know how to transfer an array + a dictionary that actually contains an identity. If you are sure that this is so, you can make two question marks.

(This compiles on the playground, but I don't have an array containing a dictionary containing an identifier convenient for testing, so caveat emptor.)

+4
source

Source: https://habr.com/ru/post/970547/


All Articles