Tuesday, October 31, 2017

Swift websockets not accepting client certificate

Leave a Comment

I am working on a project that requires client certificate support with websockets. I am currently using Starscream, however unfortunately from reading the documentation, it does not seem to have any information regarding support for this. I have looked around at few other swift web socket libraries, but none of them mention support for this

Does anyone know of any libraries that support such functionality?

Any information would be much appreciated!!

Edit:

So I am currently using Starscream to try this. I have got the certificate setup. here is the code I am trying so far

public struct IdentityAndTrust {     public var identityRef:SecIdentity     public var trust:SecTrust     public var certData : Data }      var socket = WebSocket(url: URL(string: "\(ConstantKeys.ipAddress)")!, protocols: [])     var identityTest : IdentityAndTrust?   func createTrust() {     do     {         let urlPath     = Bundle.main.path(forResource: "client", ofType: "p12")         let url         = NSURL.fileURL(withPath: urlPath!)         let certificateData = try Data(contentsOf: url)          identityTest = extractTrustAndIdentity(certData: certificateData, certPassword: ConstantKeys.password)     }     catch     {         print(error)     } }  func extractTrustAndIdentity(certData:Data, certPassword:String) -> IdentityAndTrust {     var identityAndTrust:IdentityAndTrust!     var securityError:OSStatus = errSecSuccess      var items: CFArray?     let certOptions: Dictionary = [ kSecImportExportPassphrase as String : certPassword ];     // import certificate to read its entries     securityError = SecPKCS12Import(certData as CFData, certOptions as CFDictionary, &items);     if securityError == errSecSuccess {          let certItems:CFArray = items as CFArray!;         let certItemsArray:Array = certItems as Array         let dict:AnyObject? = certItemsArray.first;          if let certEntry:Dictionary = dict as? Dictionary<String, AnyObject> {              // grab the identity             let identityPointer:AnyObject? = certEntry["identity"];             let secIdentityRef:SecIdentity = identityPointer as! SecIdentity!;              // grab the trust             let trustPointer:AnyObject? = certEntry["trust"];             let trustRef:SecTrust = trustPointer as! SecTrust;              // grab the certificate chain             var certRef: SecCertificate?             SecIdentityCopyCertificate(secIdentityRef, &certRef);             let certArray:NSMutableArray = NSMutableArray();             certArray.add(certRef as SecCertificate!);              identityAndTrust = IdentityAndTrust(identityRef: secIdentityRef, trust: trustRef, certData : certData);         }     }     return identityAndTrust } 

I then connect socket like so

let key = SecTrustCopyPublicKey(identityTest!.trust)!;     let ssl =  SSLCert(key: key)      socket.security = SSLSecurity(certs: [ssl], usePublicKeys: false)     socket.enabledSSLCipherSuites = [TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384]     socket.delegate = self     socket.connect() 

But I got the following error message

CFNetwork SSLHandshake failed (-9807)

TCP Conn 0x604000173980 SSLHandshake failed (-9807) websocket is disconnected: The operation couldn’t be completed. (OSStatus error -9807.)

I know the certificate is valid as I use it to make https requests and it works fine. So does anyone know why it is not working? Or does anyone know of another socket library that would help with this issue?

2 Answers

Answers 1

You can do the SSL pinning by simply using NSURLSession (URLSession) without using any third party library but if you still want to use one, SocketRocket, AFNetworking have support for it.

The links below should help you:

http://www.yeradis.com/swift-authentication-challenge

http://www.indelible.org/ink/trusted-ssl-certificates/

https://jetforme.org/2013/05/validating-a-self-signed-ssl-certificate-in-ios-and-os-x-against-a-changing-host-name/enter link description here

Any methods you choose (third party or URLSession), I suggest that you do read this security issue:

https://github.com/facebook/SocketRocket/pull/534

https://www.synopsys.com/blogs/software-security/ineffective-certificate-pinning-implementations/enter link description here

Answers 2

self.urlSession?.dataTaskWithURL(NSURL(string:self.urlTextField.text!)!, completionHandler: { (NSData data, NSURLResponse response, NSError error) Void in // response management code }).resume()

If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment