AdamM
AdamM

Reputation: 4430

Swift websockets not accepting client certificate

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?

Upvotes: 4

Views: 1292

Answers (1)

Anand
Anand

Reputation: 864

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

Upvotes: 0

Related Questions