Swift iOS Client Certificate Authentication -


the web service want consume requires client certificate. how can send certificate it?

to further elaborate don't understand how create secidentityref.

in nsurlconnection didreceiveauthenticationchallenge i've got conditional after servertrust:

else if challenge?.protectionspace.authenticationmethod == nsurlauthenticationmethodclientcertificate     {         var secident : secidentityref = ?????????         var certcred = nsurlcredential(identity: secident, certificates: [getclientcertificate()], persistence: nsurlcredentialpersistence.permanent)         challenge?.sender.usecredential(certcred, forauthenticationchallenge: challenge!)     } 

the getclientcertificate method:

func getclientcertificate() -> seccertificateref {     let mainbundle : nsbundle = nsbundle.mainbundle()     var mainbund = mainbundle.pathforresource("iosclientcert", oftype: "cer") //exported cert in der format.     var key : nsdata = nsdata(contentsoffile: mainbund!)!     var turntocert : seccertificateref = seccertificatecreatewithdata(kcfallocatordefault, key).takeretainedvalue()      return turntocert; } 

technically, when know needed implementation in swift, used following objective-c implementation in order nsurlcredential object connection; based on private key , x509 certificate pair contained in pkcs12 keystore.

sorry, don't have access source swift solution. know nsurlcredential returned swift, , used directly in http url connection there. it's similar one, though.

i'm not ios dev won't able out "bridging swift" part.

- (void)getmessagewithurl:(nsstring *)url {      nsurl *url = [nsurl urlwithstring:url];      nsmutableurlrequest *request = [[nsmutableurlrequest alloc] init];     [request seturl:url];     [request sethttpmethod:@"get"];     nsurlconnection *connection = [[nsurlconnection alloc] initwithrequest:request delegate:self];     [connection self]; }  - (void)postmessagewithurl:(nsstring *)url withcontent:(nsstring *)content {      nsdata *postdata = [content datausingencoding:nsutf8stringencoding];     nsstring *postlength = [nsstring stringwithformat:@"%d", [postdata length]];      nsurl *myurl = [nsurl urlwithstring:url];     nsmutableurlrequest *request = [nsmutableurlrequest requestwithurl:myurl cachepolicy:nsurlrequestreloadignoringlocalcachedata timeoutinterval:60];      [request sethttpmethod:@"post"];     [request setvalue:postlength forhttpheaderfield:@"content-length"];     [request setvalue:@"application/json" forhttpheaderfield:@"content-type"];     [request sethttpbody:postdata];      nsurlconnection *connection = [[nsurlconnection alloc] initwithrequest:request delegate:self];     [connection self];  }  - (bool)connection:(nsurlconnection *)connection canauthenticateagainstprotectionspace:(nsurlprotectionspace *)protectionspace {     return [protectionspace.authenticationmethod isequaltostring:nsurlauthenticationmethodservertrust]; }  - (void)connection:(nsurlconnection *)connection didreceiveauthenticationchallenge:(nsurlauthenticationchallenge *)challenge {     nslog(@"didreceiveauthenticationchallenge"); }  - (void)connection:(nsurlconnection *)connection didreceiveresponse:(nsurlresponse *)response {     responsedata = [[nsmutabledata alloc] init]; }  - (void)connection:(nsurlconnection *)connection didreceivedata:(nsdata *)data {     [responsedata appenddata:data]; }  - (void)connection:(nsurlconnection *)connection didfailwitherror:(nserror *)error {     nslog(@"unable fetch data");     nslog(@"%@", error); }  - (void)connectiondidfinishloading:(nsurlconnection *)connection {     nslog(@"succeeded! received %lu bytes of data", (unsigned long)[responsedata             length]);      nsstring *responsestring = [[nsstring alloc] initwithdata:responsedata encoding:nsutf8stringencoding];     nslog(@"%@", responsestring);      [bridge callhandler:handlername data:responsestring];  }  - (void)connection:(nsurlconnection *)connection willsendrequestforauthenticationchallenge:(nsurlauthenticationchallenge *)challenge {      /*     reading certificate , creating identity     */     nsarray *paths = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes);     nsstring *documentsdirectory = paths[0]; // documents directory      nsdata *p12data = [certificatemanager getp12data]; //returns byte array containing valid pkcs12 certificate      if (!p12data) {       return;       nsassert(p12data, @"couldn't load p12 file...");     }      cfstringref password = cfstr("password");      const void *keys[] = {ksecimportexportpassphrase};     const void *values[] = {password};     cfdictionaryref optionsdictionary = cfdictionarycreate(null, keys, values, 1, null, null);     cfarrayref p12items;      osstatus result = secpkcs12import((__bridge cfdataref) p12data, optionsdictionary, &p12items);      if (result == noerr) {         cfdictionaryref identitydict = cfarraygetvalueatindex(p12items, 0);         secidentityref identityapp = (secidentityref) cfdictionarygetvalue(identitydict, ksecimportitemidentity);          seccertificateref certref;         secidentitycopycertificate(identityapp, &certref);          seccertificateref certarray[1] = {certref};         cfarrayref mycerts = cfarraycreate(null, (void *) certarray, 1, null);         cfrelease(certref);          nsurlcredential *credential = [nsurlcredential credentialwithidentity:identityapp certificates:nil persistence:nsurlcredentialpersistencenone];         cfrelease(mycerts);          [[challenge sender] usecredential:credential forauthenticationchallenge:challenge];     }     else {         // certificate invalid or password invalid given certificate         nslog(@"invalid certificate or password");         nserror *error = [nserror errorwithdomain:nsosstatuserrordomain code:result userinfo:nil];         return;     } } 

edit: har har, funny, downvoting me twice when didn't bother while bounty up. *grumble *

anyways, use following above, need access swift.

func connection(connection: nsurlconnection, willsendrequestforauthenticationchallenge challenge: nsurlauthenticationchallenge) {     if let p12data = usermanager.currentp12,        let credential = certificatemanager.getcredentialsforp12(p12data) as? nsurlcredential {             challenge.sender.usecredential(credential, forauthenticationchallenge: challenge)     } else {         uiapplication.sharedapplication().networkactivityindicatorvisible = false     }    } 

that uses this.

+ (id)getcredentialsforp12:(nsdata *)p12 {     nsdata* p12data = p12;     const void *keys[] = {ksecimportexportpassphrase};     const void *values[] = {cfstr("thepassword")};     cfdictionaryref optionsdictionary = cfdictionarycreate(null, keys, values, 1, null, null);     cfarrayref p12items;     osstatus result = secpkcs12import((__bridge cfdataref) p12data, optionsdictionary, &p12items);     if (result == noerr) {         cfdictionaryref identitydict = cfarraygetvalueatindex(p12items, 0);         secidentityref identityapp = (secidentityref) cfdictionarygetvalue(identitydict, ksecimportitemidentity);         seccertificateref certref;         secidentitycopycertificate(identityapp, &certref);         seccertificateref certarray[1] = {certref};         cfarrayref mycerts = cfarraycreate(null, (void *) certarray, 1, null);         cfrelease(certref);          nsurlcredential *credential = [nsurlcredential credentialwithidentity:identityapp certificates:nil persistence:nsurlcredentialpersistencenone];         cfrelease(mycerts);         return credential;      }     else {         // certificate invalid or password invalid given certificate         nslog(@"invalid certificate or password");          uialertview* av = [[uialertview alloc] initwithtitle:@"error" message:@"invalid cert or pass" delegate:nil cancelbuttontitle:@"ok" otherbuttontitles: nil];         [av show];         nserror *error = [nserror errorwithdomain:nsosstatuserrordomain code:result userinfo:nil];         return nil;     } 

edit: swift version of above here, although messy enough rather didn't use it.

            var p12items : unmanaged<cfarrayref>?              let index: cfindex = 1             let password: cfstring = "password"             let key = ksecimportexportpassphrase.takeretainedvalue() string             var values = [unsafeaddressof(password)]             var keys = [unsafeaddressof(key)]              var keycallbacks = kcftypedictionarykeycallbacks             var valuecallbacks = kcftypedictionaryvaluecallbacks              let length: cfindex = p12data.length             let p12cfdata: cfdata = cfdatacreate(kcfallocatordefault, unsafepointer<uint8>(p12data.bytes), length)              let options = cfdictionarycreate(kcfallocatordefault, &keys, &values, index, &keycallbacks, &valuecallbacks)             let result = secpkcs12import(p12cfdata, options, &p12items)              if result == noerr {                  let idindex: cfindex = 0                 var items = p12items?.takeretainedvalue()                 var identitydict = cfarraygetvalueatindex(items!, idindex)                   var key = ksecimportitemidentity.takeretainedvalue() string                 var keyaddress = unsafeaddressof(key)                 var identityapp: secidentityref = cfdictionarygetvalue(identitydict, keyaddress)                  var certref : unmanaged<seccertificateref>?                 secidentitycopycertificate(identityapp, &certref)                  var cert: seccertificateref = certref!.takeretainedvalue()                 var certarray = [unsafeaddressof(cert)]                 var arraycallback = kcftypearraycallbacks                 var mycerts: cfarrayref = cfarraycreate(kcfallocatordefault, &certarray, index, &arraycallback);                  let credential: nsurlcredential = nsurlcredential(identity: identityapp, certificates: [anyobject](), persistence: nsurlcredentialpersistence.none) 

Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -