How do I install a root certificate authority on a device?
The certificate is only needed for my app, and can be installed in its sandbox if possible.
It works when I drag the certificate onto the simulator and install it, but not using the following code:
let rootCertPath = NSBundle.mainBundle().pathForResource("server", ofType: "der")!
let rootCertData = NSData(contentsOfFile: rootCertPath)!
let rootCert = SecCertificateCreateWithData(kCFAllocatorDefault, rootCertData).takeRetainedValue()
let error = SecItemAdd(
[
NSString(format: kSecClass): NSString(format: kSecClassCertificate),
NSString(format: kSecValueRef): rootCert
], nil)
SecItemAdd returns with no errors, and seems to be installed on the device correctly, but it still fails to connect to the server with with the error:
NSURLConnection/CFURLConnection HTTP load failed (kCFStreamErrorDomainSSL, -9813)
Code for connecting to server:
let request = NSURLRequest(URL: NSURL(string: "https://" + server + ":" + port)!)
let session = NSURLSession(configuration: .defaultSessionConfiguration())
session.dataTaskWithRequest(request, completionHandler:
{(data, response, error) in
println(error)
}).resume()
error prints the following:
Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid.
But again, if I manually install the same certificate in the simulator's profiles, it connects just fine.
This is not safe and does not require the certificate
Managed to get this working using sockets (NSStream and CFStream).
The important thing to note is that I needed to disable kCFStreamSSLValidatesCertificateChain for my certificate to work.
class Authentication: NSObject, NSStreamDelegate
{
private var inputStream: NSInputStream?
private var outputStream: NSOutputStream?
func connectToServer(server: String, port: Int)
{
let sslSettings =
[
NSString(format: kCFStreamSSLValidatesCertificateChain): kCFBooleanFalse
]
NSStream.getStreamsToHostWithName(server, port: port, inputStream: &inputStream, outputStream: &outputStream)
CFReadStreamSetProperty(inputStream, kCFStreamPropertySocketSecurityLevel, kCFStreamSocketSecurityLevelTLSv1)
CFReadStreamSetProperty(inputStream, kCFStreamPropertySSLSettings, sslSettings)
inputStream!.delegate = self
outputStream!.delegate = self
inputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
outputStream!.scheduleInRunLoop(NSRunLoop.currentRunLoop(), forMode: NSDefaultRunLoopMode)
inputStream!.open()
outputStream!.open()
}
}
Helpful links:
iOS: Pre install SSL certificate in keychain - programmatically
Overriding TLS Chain Validation Correctly
HTTPS Server Trust Evaluation
SSL Socket connection iOS
Toll-free bridging and pointer access in Swift
Adding a self-signed certificate to iphone Simulator?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With