0

I want to make sure each of my apps users only get their own data, and that nobody tampers with it or sniffs it in a MITM fashion. Encryption of everything should be the solution, right? But how do I distribute the keys?

Afaik SSL/TLS only makes sure the client is talking to the correct server, not the other way around. I want to make sure the client is who it says to be.

I thought of using asymmetric encryption to solve this. The servers public key could be included in the app, and distributed through app store/google play. Then the user would be able to talk to the server securely from the start. The client can then send it's public key securely to the server, allowing two way encrypted communication, and making sure the server is sending the data to the correct client. All of this would then be sent over https.

Am I over-complicating this? What security holes am I missing? Is there something else I would need to make this secure? I don't want to reinvent the wheel, so an existing solution would be preferred.

  • What is your threat model? For the majority of cases authenticating your clients is enough. If you're paranoid, you can indeed get them to give you a public key (remember you have no idea who is giving the key in the first place over the Internet so you should ideally use a different transmission channel). You could also require clients to connect to a specific VPN with IPSEC turned on, I guess... Hopefully others can give more detailed answers (network not my thing). – Steve Dodier-Lazaro Jul 12 '14 at 15:45
  • I don't know who's sending me the key, but I know that the following connections using that key will be from the same user, right? That's my goal. – Filip Haglund Jul 12 '14 at 19:54
  • Exactly. In that case you'd just need, upon the first connection of a client, to serve them a unique, unforgeable token that they need to bring back with them. Stealing the token would of course allow for impersonation. Network/Web people should be able to provide accurate answers, hopefully. – Steve Dodier-Lazaro Jul 12 '14 at 20:36
2

You want mutual authentication between client and server.

As per the SSL/TLS protocol, this is supported with client certificates. Both the server and the client have a certificate; the server shows its certificate to the client, and then requests the client to show its own certificate and prove control of the corresponding private key. This works, this is standard, this is supported by usual libraries; but it requires, of course, the client to actually have an installed certificate.

The double-certificate model is fine in cases where the client does not actually trusts the server. In your case, you can do something simpler, because your app trusts your server (the app wants to be sure that it talks to the genuine server, but once it has such assurance, it talks freely with no restraint): you can use the show-the-password model that is really common throughout the Web. In full details:

  • When the application is first installed or started, it talks to your server, identifying it through its certificate. The SSL protocol makes sure that what the app will send really goes to your server only, and cannot be altered or spied upon while in transit.
  • During that first connection, the app generates a random value K and stores it locally; it also says to your server: "Hello, I am a new client and my key is K".
  • Your server stores in its database the information about the new client, including h(K) where h() is a cryptographic hash function (say, SHA-256).
  • Later on, when the app reconnects, it opens a new SSL connection, there again making sure that it talks to the right server (thanks to the server's certificate); and it then sends K to the server. The server computes h(K) (on the K value from the client) and compares it with the stored value; if there is a match, then the server knows that it is the same client as previously.

When K is something that the human user remembers and types (a "password"), a lot of extra care must be taken, especially with the hash function h() which should then be something quite more complex than SHA-256. But here, the K value is generated and stored by an application, who can use a cryptographically strong PRNG and handle a K of 128 bits or more, which will be immune to the kind of attacks that apply to passwords.


Of course, all of this is about protecting the client-server communication from outsiders. The client itself (i.e. the app user) can reverse-engineer the app at will; you cannot make sure that what is on the client side is "your app", unmodified. However, SSL and the show-the-password concept allow you to make sure that if the data goes into the wrong hands, then the client himself is dishonest (or his smartphone was stolen).

  • Would it be useless to further encrypt the data inside ssl/tls? Like using twofish to encrypt the data before sending it through ssl/tls? – Filip Haglund Jul 13 '14 at 14:22
  • 2
    Yes, it would be useless to "further encrypt" the data -- unless the goal is not to have extra security, but to woo an incompetent auditor by piling up algorithms as if cryptography was some sort of curry. – Thomas Pornin Jul 13 '14 at 14:52

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.