I'm trying to set up a client connection to communicate with an MQTT broker using client side certificates. I've been able to proof-of-concept this all on the Linux side using command line. The MQTT broker is set to require client cert, and a command like:
mosquitto_pub -h servername -p 8899 -t 1234/2/Q/8 -m myMessage --cafile myChain.crt --cert client.crt --key client.pem
does the job nicely. Now I'm trying to set up an NWConnection:
self.connection = NWConnection( host: NWEndpoint.Host("servername"), port: NWEndpoint.Port(integerLiteral: 8899), using: .tls)
But I think that simple .tls class var needs to be a much more involved NWParameters object, but I'm at a complete loss (documentation is pretty sparse) as to what I create there to attach the client certs to the parameters. Nor do I know how I even move from .crt/.pem file to something the app manages programatically.
What is an example of how one would configure the NWParameters to support the client certs?
Sorry I didn’t respond sooner; somehow I missed your post when it first showed up )-:
What is an example of how one would configure the NWParameters to support the client certs?
Yeah, that’s a bit tricky. The basic structure for this as as follows:
let options = NWProtocolTLS.Options() let securityOptions = options.securityProtocolOptions … configure `securityOptions` here … let params = NWParameters(tls: options) let conn = NWConnection(host: "example.com", port: 443, using: params)
The above gives you access to the
sec_protocol_options_t
, allowing you to customise various TLS operations. For example:
To customise server trust evaluation, set a verify block:
sec_protocol_options_set_verify_block(securityOptions, { (_, trust, completionHandler) in let isTrusted = … your code here … completionHandler(isTrusted) }, .main) .
To always supply a client identity, set it as the local identity:
let clientIdentity: SecIdentity = … your code here … sec_protocol_options_set_local_identity( securityOptions, sec_identity_create(clientIdentity)! ) .
To respond to client certificate challenges from the server — this allows you to pick an identity based on info returned to you by the server — set a challenge block:
sec_protocol_options_set_challenge_block(securityOptions, { (_, completionHandler) in let clientIdentity: SecIdentity = … your code here … completionHandler(sec_identity_create(clientIdentity)!) }, .main) .
Share and Enjoy
—
Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware
let myEmail = "eskimo" + "1" + "@apple.com"