SWIFT: server certificate does NOT include an ID which matches the server name

I'm working on MBP OSX Ventura 13.5.2 I'm working with Swift 5 (Xcode 15.2) I have a local httpd configured with vhosts. I create my local certs using mkcert.

When I visit the https://example site with Chrome the certificate is perfectly valid and there are no issues.

When I try and contact the same site using a DataCallBack function to the URL I get the error "server certificate does NOT include an ID which matches the server name"

In the log:

Connection 1: default TLS Trust evaluation failed(-9807)
Connection 1: TLS Trust encountered error 3:-9807
Connection 1: encountered error(3:-9807)

Answered by DTS Engineer in 802047022
So I dragged my CA root certificate (JacarandaCA.p12) to the simulator

That’s not right. You don’t want to install the digital identity, but rather just the certificate.

I ran through these steps today, just to be sure, and things are still working for me. Here’s what I did:

  1. Using Xcode 16.0b6 on macOS 14.6.1, targeting the iOS 18.0b7 simulator…

  2. Create a new app project from the iOS > App template.

  3. Add a Test button and wire it up to the test function; the code for that is at the end of this post.

  4. Build and run it on the simulator.

  5. In the simulator, tap the app’s Test button. It logs:

    will run task
    did not run task, error: NSURLErrorDomain / -1200
    

    As expected, the app can’t access https://www.cacert.org because its certificate was not issued by a trusted root.

  6. Stop the app.

  7. On the Mac, go to the CAcert website http://www.cacert.org/index.php?id=3 and download Root Certificate (DER Format). That yields a file called root_X0F.der.

  8. Drag that into the simulator.

  9. In the simulator, there’s an alert saying “This website is trying to download a configuration profile. Do you want to allow this?” Tap Allow.

  10. There’s a second alert saying “Profile Downloaded; Review the profile in the Settings app if you want to install it.” Tap Close.

  11. Still in the simulator, launch Settings.

  12. There’s now a Profile Downloaded entry. Tap it.

  13. Run through the install process.

  14. Once you’re done, navigate to Settings > About > Certificate Trust Settings and enable CA Cert Signing Authority.

  15. Back in Xcode, run the app again.

  16. And in the app, tap the Test button again. It prints:

    will run task
    did run task, status: 200, bytes: 15280
    

    The app is now able to access https://www.cacert.org because the CAcert root is installed in the simulator.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"


func test() async {
    do {
        print("will run task")
        let url = URL(string: "https://www.cacert.org")!
        let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
        let (data, response) = try await URLSession.shared.data(for: request)
        let httpResponse = response as! HTTPURLResponse
        print("did run task, status: \(httpResponse.statusCode), bytes: \(data.count)")
    } catch let error as NSError {
        print("did not run task, error: \(error.domain) / \(error.code)")
    }
}
I've been on holiday.

Likewise.

I’m glad you’re making progress here. Putting the root certificate into the System keychain was the correct solution to your -9813 (errSSLNoRootCert) issue.

Regarding the -9807 (errSSLXCertChainInvalid) issue, it’s hard to say what’s going on there without more details. Specifically:

I checked it first with Safari, and the certificates worked fine.

That looks like Safari on your Mac. That’s a useful test, but it doesn’t say anything about the behaviour of the simulator. The simulator runs its own TLS server trust evaluation, independent of the Mac it’s running on.

QA1948 explains how to install a trusted root on the simulator. Did you try that? If not, please do.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn

Sorry - your response never appeared after my 27 Aug post, but then again I didn't see the "Page 1 of 2". When I checked the next page I can now see it.

So I dragged my CA root certificate (JacarandaCA.p12) to the simulator (iPhone 15 pro) and a dialog popped up about downloading something from somewhere (it didn't say anything about certificates) - I said yes. Then Safari started on the Simulator and it went to this page https://support.apple.com/en-us/103272 ... no idea why it went there...

I then reran my mobile app and got the same error. -9807

Contact URL = https://xpedite.local/rx/rx.php
Connection 1: default TLS Trust evaluation failed(-9807)
Connection 1: TLS Trust encountered error 3:-9807
Connection 1: encountered error(3:-9807)
Task <34F622E9-8ED6-4562-A5D7-ADBA73B30CE0>.<1> HTTP load failed, 0/0 bytes (error code: -1202 [3:-9807])
Task <34F622E9-8ED6-4562-A5D7-ADBA73B30CE0>.<1> finished with error [-1202] Error Domain=NSURLErrorDomain Code=-1202 "The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xpedite.local” which could put your confidential information at risk." UserInfo={NSLocalizedRecoverySuggestion=Would you like to connect to the server anyway?, _kCFStreamErrorDomainKey=3, NSErrorPeerCertificateChainKey=(
    "<cert(0x10684ca00) s: xpedite.local i: Jacaranda>"
), NSErrorClientCertificateStateKey=0, NSErrorFailingURLKey=https://xpedite.local/rx/rx.php, NSErrorFailingURLStringKey=https://xpedite.local/rx/rx.php, NSUnderlyingError=0x600000c58db0 {Error Domain=kCFErrorDomainCFNetwork Code=-1202 "(null)" UserInfo={_kCFStreamPropertySSLClientCertificateState=0, kCFStreamPropertySSLPeerTrust=<SecTrustRef: 0x600003301180>, _kCFNetworkCFStreamSSLErrorOriginalValue=-9807, _kCFStreamErrorDomainKey=3, _kCFStreamErrorCodeKey=-9807, kCFStreamPropertySSLPeerCertificates=(
    "<cert(0x10684ca00) s: xpedite.local i: Jacaranda>"
)}}, _NSURLErrorRelatedURLSessionTaskErrorKey=(
    "LocalDataTask <34F622E9-8ED6-4562-A5D7-ADBA73B30CE0>.<1>"
), _kCFStreamErrorCodeKey=-9807, _NSURLErrorFailingURLSessionTaskErrorKey=LocalDataTask <34F622E9-8ED6-4562-A5D7-ADBA73B30CE0>.<1>, NSURLErrorFailingURLPeerTrustErrorKey=<SecTrustRef: 0x600003301180>, NSLocalizedDescription=The certificate for this server is invalid. You might be connecting to a server that is pretending to be “xpedite.local” which could put your confidential information at risk.}

I'm assuming that my CA root certificate has not loaded (or is not trusted).
When I drop the CA root (.p12) on the simulator what is supposed to happen. In all my googling I've never seen any documentation (screen shots) of what should happen when I do this.

Cheers Murray

So I dragged my CA root certificate (JacarandaCA.p12) to the simulator

That’s not right. You don’t want to install the digital identity, but rather just the certificate.

I ran through these steps today, just to be sure, and things are still working for me. Here’s what I did:

  1. Using Xcode 16.0b6 on macOS 14.6.1, targeting the iOS 18.0b7 simulator…

  2. Create a new app project from the iOS > App template.

  3. Add a Test button and wire it up to the test function; the code for that is at the end of this post.

  4. Build and run it on the simulator.

  5. In the simulator, tap the app’s Test button. It logs:

    will run task
    did not run task, error: NSURLErrorDomain / -1200
    

    As expected, the app can’t access https://www.cacert.org because its certificate was not issued by a trusted root.

  6. Stop the app.

  7. On the Mac, go to the CAcert website http://www.cacert.org/index.php?id=3 and download Root Certificate (DER Format). That yields a file called root_X0F.der.

  8. Drag that into the simulator.

  9. In the simulator, there’s an alert saying “This website is trying to download a configuration profile. Do you want to allow this?” Tap Allow.

  10. There’s a second alert saying “Profile Downloaded; Review the profile in the Settings app if you want to install it.” Tap Close.

  11. Still in the simulator, launch Settings.

  12. There’s now a Profile Downloaded entry. Tap it.

  13. Run through the install process.

  14. Once you’re done, navigate to Settings > About > Certificate Trust Settings and enable CA Cert Signing Authority.

  15. Back in Xcode, run the app again.

  16. And in the app, tap the Test button again. It prints:

    will run task
    did run task, status: 200, bytes: 15280
    

    The app is now able to access https://www.cacert.org because the CAcert root is installed in the simulator.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"


func test() async {
    do {
        print("will run task")
        let url = URL(string: "https://www.cacert.org")!
        let request = URLRequest(url: url, cachePolicy: .reloadIgnoringLocalCacheData, timeoutInterval: 60.0)
        let (data, response) = try await URLSession.shared.data(for: request)
        let httpResponse = response as! HTTPURLResponse
        print("did run task, status: \(httpResponse.statusCode), bytes: \(data.count)")
    } catch let error as NSError {
        print("did not run task, error: \(error.domain) / \(error.code)")
    }
}

Hi Quinn

This is easy because the website supplies the specific .DER file required. I tried a few ideas to create a .DER key but they didn't work. (From my reading the .DER file is a binary format of the public key - not the certificate, however the definition is irrelevant, we just need to generate the file).

I went back to the Certificant Assistant and looked for options to create a .DER format of the public key, the private key, the certificate, anything actually, and there is no such option.

I did find some openssl commands that would output a .DER file, but none of those options were successful. Generally when I dropped them on the Simulator an error appeared "Profile error".

So how do I generate a .DER file from my test environment Root CA, that will load into the Simulator?

Cheers Murray

So how do I generate a .DER file from my test environment Root CA

If you’re starting with a PKCS#12 (.p12), using openssl to export the certificate as a PEM:

% openssl pkcs12 -info -in root.p12 -nokeys  

Once you have a certificate PEM, using openssl to convert it to DER format:

% openssl x509 -in root.pem -out root.cer -outform der

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Hi Quinn

Why does every step have to be another problem????? Sorry, getting a bit frustrated with this process.

murraycollingwood@192-168-1-17 local-cert % openssl pkcs12 -info -in Jacaranda.p12 -nokeys                   
Enter Import Password:
MAC: sha1, Iteration 1
MAC length: 20, salt length: 8
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
Error outputting keys and certificates
80A0ECE301000000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:355:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()

I also tried specifying the output but that didn't help either:

murraycollingwood@192-168-1-17 local-cert % openssl pkcs12 -info -in Jacaranda.p12 -nokeys -out Jacaranda.pem
Enter Import Password:
MAC: sha1, Iteration 1
MAC length: 20, salt length: 8
PKCS7 Encrypted data: pbeWithSHA1And40BitRC2-CBC, Iteration 2048
Error outputting keys and certificates
80A0ECE301000000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:crypto/evp/evp_fetch.c:355:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()

No PEM file is being generated. What can I try next?

Cheers Murray

Can you import that .p12 into Keychain Access?

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

The CA Jacaranda.p12 was exported from Keychain Access.
Sorry, I'm not sure what the purpose is of importing it back into Keychain Access when it originated from there??? Can you explain your thinking please?

Cheers Murray

The CA Jacaranda.p12 was exported from Keychain Access.

Ah, sorry, I thought you’d got the PKCS#12 from elsewhere.

If you have the PKCS#12 in Keychain Access, you can export the certificate from there:

  1. Switch to the All Items tab.

  2. Select just the certificate.

  3. Choose File > Export Items.

  4. The File Format popup should default to Certificate (.cer). If not, select that.

  5. Drop the result .cer file on to the simulator.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Accepted Answer

The final solution:

This site was helpful: https://blog.arrogantrabbit.com/ssl/Root-CA-macOS/

Create a Certificate for our local development

Using the Certificate Assistant to first create a Root CA for the computer "Jacaranda" (store in "System") Using the Certificate Assistant to create a leaf Certificate for the domain xpedite.local (store in "Login")

Trust the certificate authority.

Export the certificate authority to local-cert using the .cer format. I'm creating Jacaranda.cer We can drag and drop this RootCA .cer file onto the simulator to install it. Inside the simularor you can check in Settings | General | About | Certificate Trust Settings to ensure it has been installed.

Export the leaf certificate to local-cert using the .cer format. I'm creating xpedite.local.cer You will be prompted for a password, I'm using '***********'

Export the leaf key to local-cert using the .p12 format. I'm creating xpedite.local.p12 You will be prompted for a password, I'm using '***********'

Run the commands: openssl x509 -inform der -in xpedite.local.cer -out xpedite.local.crt openssl pkcs12 -in xpedite.local.p12 -out xpedite.local.key -nodes -legacy

Check the file names in the apache2/extra/httpd-vhosts.conf And then restart apache: sudo apachectl restart

Seems simple enough.... 😄

And a big thank you to Quinn - couldn't have done it without you!

SWIFT: server certificate does NOT include an ID which matches the server name
 
 
Q