I am fairly new to encryption and I need some help. I have a problem that I'm trying to solve.

My problem is the following:

  • I have a Web Server and an (iOS) App that that communicate with each other.
  • I want the communication to be secure, so I'm using HTTPS.
  • The Web Server and the App are communicating via an intranet, with no access to the internet on either end.
  • Since there is no connection to the internet, the SSL Certificate on the Web Server is self signed, and cannot be verified against a CA.

So my problem is that when I establish an HTTPS connection, the Certificate cannot be trusted because it can't be verified, so MITM attacks are possible. So what I need is a way to verify the Certificate without resorting to a CA.

My idea is to start by establishing a secure connection between the App and the Web Server using Diffie-Hellman to transfer the certificate, so that when the SSL connection is being established, I can verify if the certificate is correct.

Would this work? Or is it somehow still susceptible to MITM or other attacks? If it is, then how else can I solve my problem?

Also, it's worth mentioning that each of my customers will have their own Web Server and therefore their own self-signed certificates. So embedding the public key into the App is not an option.

5 Answers 5


I don't think you understand fully what you are doing so I try to explain your steps:

...start by establishing a secure connection between the App and the Web Server using Diffie-Hellman..

This would be an anonymous DH connection because you don't verify the identity of the peer. And you can't verify its identity because you have no trust anchor yet. Because you don't verify the identity you cannot be sure who you are talking with. This means also that MITM attacks are possible so you should not trust any data you get inside this connection.

... to transfer the certificate, so that when the SSL connection is being established, I can verify if the certificate is correct.

This means you transfer a trust anchor for future connections using an untrusted connection which is open to MITM attacks. There is no way to verify that the certificate you got is actually the certificate of the peer you liked to talk with and not the certificate of the attacker.

In summary: You replace "no verification because no trust anchor" with "verification against actually untrusted trust anchor".

  • Thank you for your explanation. I understand the problem with my idea. Do you know of any other possible solutions to this problem?
    – Rob
    Commented Nov 9, 2014 at 16:53
  • @Rob: the usual way is to ship the trust together with the application, that is use certificate pinning. Using a certificate issued by a public CA already trusted by the browser would also work because you don't need internet to verify the certificate. But often these CA do not issue certificates for internal sites because they might conflict with external hosts in the future. Commented Nov 9, 2014 at 17:25
  • Thank you for your answers! I understand. I'm marking this as the answer since it is the best explanation.
    – Rob
    Commented Nov 10, 2014 at 17:23

You write:

Since there is no connection to the internet, the SSL Certificate on the Web Server is self signed, and cannot be verified against a CA.

There is some misconception here. Let's restate some fundamental elements about certificates:

  • Certificates don't get or lose value depending on how you obtain them. What matters for a certificate is who signed it.
  • You don't need any connection to the Internet. In fact that is the whole point of certificates: they are a way to bind names to public keys in a way that can be validated without having to talk to a third party system. Certificates are meant to work for offline systems.
  • A certificate is validated with regards to an a priori known "trust anchor" (aka "root CA"). A self-signed certificate is a certificate that purports to be its own root CA.
  • Doing a prior Diffie-Hellman key exchange changes nothing to any of the above. None of the signatures on all these certificates creates any trust; the trust is transferred but must still start somewhere, i.e. the trust anchors. You cannot conjure trust out of thin air, be it with Diffie-Hellman or any other cryptographic algorithm.
  • Even if your systems had some connection to the Internet, nothing would be changed.

In your case, you want the client (iOS App) to be able to check that it talks to the genuine server (your Web Server). The simplest method for that is to use a self-signed certificate in the server, and hardcode a copy of that certificate in the App. Just to avoid any misunderstanding: the certificate contains the public key but not the private key; the server will have both the certificate and the private key, the App will know only the certificate. With the hardcoded certificate, the App can make sure that it talks to the right server by virtue of using the public key in that hardcoded certificate; in other words, the App validates the certificate that the server sends by comparing it, bit-by-bit, with the one already included in the App entrails.

A somewhat more complex but maybe more flexible method is to run your own CA. You create a self-signed root CA and install the corresponding certificate in the App as a trust anchor. You also issue (i.e. sign) with that CA a certificate for the server. The App will apply normal X.509 validation, i.e. verify that the certificate sent by the server is indeed signed by one of its trust anchors.

  • Thank you for your explanations and suggestions. However, I cannot embed the certificate into the App, since the certificate will be different for each costumer. Otherwise, this would be ideal.
    – Rob
    Commented Nov 9, 2014 at 17:00
  • Having a different certificate for each customer means that you have a different server side endpoint for each customer and that each instance of the app needs to be somehow configured to use the customer specific endpoint. If you provide the configuration for each customer you could also include the certificate information with the configuration. And if you roll your own CA you only need to include the CA as trusted in your app and verify the name of the endpoint against the certificate signed by the CA. Commented Nov 10, 2014 at 7:05

What you want to do fundamentally violates the "Fundamental Principle of Trust" as stated by Rajput which states that "To establish trust between two parties on an untrusted you need an "External" trust channel (such as a third party)".

If the problem is that you truly do not trust the certificate, adding the cert into the trusted store is not an option. One solution is to issue all certificates using a single CA and then keep that certificate on all devices or install it at "initialization of Trust" moment. Initialization of Trust is always the most risky moment and should be only done through one of the following options (e-mail is not secure):

  1. Physically bring the device in a trusted "zone.
  2. Through a Third party that is trusted by both (i.e. deliver the cert by FedEx, or hand deliver it)



You should be able to use certificates from a trusted authority even without an Internet connection. You'll need to have an internet connection to get the certificate (and any relevant intermediate CA certificates), but once it's purchased you can transfer it to the intranet, and install it on the web server.

The only potential source of trouble is that the client will not be able to check the certificate's revocation status without an Internet connection, but my understanding is that iOS will allow SSL/TLS connections to go through even if it can't reach the revocation (CRL or OCSP) server.

EDIT: I thought of another possible issue: the client must reach the server using a proper domain name that's actually registered to the company -- no "server.local," "server.private," or IP address. Note that while the company's regular DNS servers will not be reachable on the intranet, it's generally possible to set up a private DNS server on the intranet (in fact, they might already have one).


You can add the certificate to the device's list of trusted certificates; this site has a description of how to do so, but basically, you can email the certificate to each device, or you can use Apple iPhone management tools to add them to many devices. It seems like your product will involve setup instructions (as the server has to be set up, they can't just download the app), so you could add that to the instructions.

EDIT: Diffie-Hellman, in addition to being susceptible to man-in-the-middle attacks, is entirely unsuited to your goals. What DH does is enable parties to negotiate a shared secret across an insecure channel without having to have shared a secret over a secure channel. Neither party can meaningfully control what that shared secret is; DH is not an encryption technique, because that requires Alice to be able to send Bob something of her choice, and all DH does is give them both something that they know and no one else does. You can apply a symmetric encryption after doing DH (ElGamal is basically that), but DH itself can't transfer information of your choice.

Also, DH has no protection against MitM attacks, and so the information transmitted has to be made trustworthy somehow (whether that be by bundling it in the app [though you've rejected using the same cert for everyone, and the same issue shows up with reusing DH credentials], or by signing it [this is literally how some SSL modes work]). So no, DH isn't what you're looking for.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .