I am trying to establish a simple socket connection (NO HTTP) from my iOS app to my backend server (Node.js). The servers certificate has been created and signed using a custom CA that I made myself. I believe that in order to get iOS to trust my server I will have to somehow add this custom CA Certificate to the list of trusted certificates that are used to determine trust sort of how a TrustStore in Java/Android works.
I have tried to connect using the code below and there are no errors however the write() function does not seem to succeed.
Main View Controller:
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let api: APIClient = APIClient()
api.initialiseSSL("10.13.37.200", port: 8080)
api.write("Hello")
api.deinitialise()
print("Done")
}
APIClient class
class APIClient: NSObject, NSStreamDelegate {
var readStream: Unmanaged<CFReadStreamRef>?
var writeStream: Unmanaged<CFWriteStreamRef>?
var inputStream: NSInputStream?
var outputStream: NSOutputStream?
func initialiseSSL(host: String, port: UInt32) {
CFStreamCreatePairWithSocketToHost(kCFAllocatorDefault, host, port, &readStream, &writeStream)
inputStream = readStream!.takeRetainedValue()
outputStream = writeStream!.takeRetainedValue()
inputStream?.delegate = self
outputStream?.delegate = self
inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
let cert: SecCertificateRef? = CreateCertificateFromFile("ca", ext: "der")
if cert != nil {
print("GOT CERTIFICATE")
}
let certs: NSArray = NSArray(objects: cert!)
let sslSettings = [
NSString(format: kCFStreamSSLLevel): kCFStreamSocketSecurityLevelNegotiatedSSL,
NSString(format: kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse,
NSString(format: kCFStreamSSLPeerName): kCFNull,
NSString(format: kCFStreamSSLCertificates): certs,
NSString(format: kCFStreamSSLIsServer): kCFBooleanFalse
]
CFReadStreamSetProperty(inputStream, kCFStreamPropertySSLSettings, sslSettings)
CFWriteStreamSetProperty(outputStream, kCFStreamPropertySSLSettings, sslSettings)
inputStream!.open()
outputStream!.open()
}
func write(text: String) {
let data = [UInt8](text.utf8)
outputStream?.write(data, maxLength: data.count)
}
func CreateCertificateFromFile(filename: String, ext: String) -> SecCertificateRef? {
var cert: SecCertificateRef!
if let path = NSBundle.mainBundle().pathForResource(filename, ofType: ext) {
let data = NSData(contentsOfFile: path)!
cert = SecCertificateCreateWithData(kCFAllocatorDefault, data)!
}
else {
}
return cert
}
func deinitialise() {
inputStream?.close()
outputStream?.close()
}
}
I understand how SSL/TLS works and all since I have done this all fine in the Android version of this same app. I am just confused with the iOS implementation of SSL.
I am from a Java background and have been going with this problem for 3 weeks. Any help would be appreciated.
Prefer answers in Swift code, not Objective C but if you only have Obj C thats ok too :)