10

Background

I'm trying to design a secure and sustainable web app for messaging. The purpose is to learn how to create secure web application.

The application is suppose to be written in Javascript for web based clients and PHP for server-side.

Clients using the web application will log in to be able to use the service on a wide variety of devices.

Clients can then send messages to other users - securely without any middle hand being able to read the message in clear text. I don't want the server to be able to read the messages either, therefore the main encryption will have to happen client-side.


Thoughts

  • SSL/TLS - ensure valid communication with server
  • RSA - asymmetric encryption - for encrypting encryption keys
  • AES - to encrypt unknown amount of data, most commonly plain text

The whole application will obviously be built using SSL / TLS to allow secure and validated communication between the client and the server.

To ensure that only the intended parties get access to the sent data, asymmetric encryption is used. Every client has their own private keys stored client-side and their public keys stored on the server attatched to the user in a database.

When Alice wants to write a message to Bob, she encrypts the data with a strong AES key - since RSA can only handle a finite data size. To ensure that only Bob can read the message, she retrieves Bob's public key from the database and encrypts her generated AES key with it. The encrypted message is then sent to the server - along with the key used - encrypted with Bob's public key.

Bob retrieves this message / key pair from the server. Since Bob has the private key related to the used public key for encrypting Alice's message's key - he and only he can retrieve the used key in plain text. Using this unencrypted key he can then decrypt the main message and read it as plain text.


Concerns

The public and private key pair has to be generated server-side. This forces the private key to be sent to the user for use. How can this be made safe, since any middle-man can retrieve the private key to further use to decrypt all of Alice's messages.

To ensure that the server doesn't know what messages users send, it cannot have access / store the private keys. This forces the keys to be stored client-side - using Javascript, a language and platform rarely associated to security or secure data persistence. Since security is of my main concern, not properly storing the private keys is a major problem.

Let's say the user wants to log in and use the application from another device, then the private key has to 'magically' appear there as well. Forcing the server to store the private keys anyway. Is there any other way to do this encryption / key management?


Clarifying questions

If the above topics are too long to read, confusing or if you're just in a hurry, below are simplified questions.

How can I ensure messages being sent between can only be read by those two parties?

How can I ensure my users that I / the server or anyone else for that matter, can read their messages?

If their is a way of storing the private keys securely client-side, how bad is it?

Alex
  • 500
  • 3
  • 14
  • 2
    Public key management is one of the harder concepts to tackle. You are right in thinking that generating the public/private key pair server side is insecure. – RoraΖ Mar 26 '15 at 11:38

2 Answers2

4

I think there is an additional problem/challenge with your scheme: Beside the problem of having the key pairs generated by the server, this scheme also allows for a man in the middle attack: A asks for the key of B, server answers with his own key C. Now the server can decrypt, read and encrypt again for B and send the new ciphertext to B. Neither A nor B will ever notice as long as the communication is done using the server. To prevent this, you need to decouple key management server and message server. In the best case, you would use an active community key server like the ones for pgp for example.

Anyway, assuming the key management is done honestly, your hybrid encryption should work out.

Concerning the key generation, have a look at CryptoJS. If I remember correctly, it is (almost) a full-fledged crypto framework that can also generate keys. You could use html5's local storage API to store the key client-side.

user3363866
  • 256
  • 2
  • 6
  • 1
    Now that you mention it that is obvious. So generate the key pair client-side and then sending the public key to the server is the obvious way to go. If the server only has the public key, it cannot decrypt messages meant for anyone else, only encrypt them - right? I want to do as much client-side as possible and trust the server as little as possible. Storing the private key using local storage is only feasible if it gets encrypted with a key derived from the password - correct? My final question is, how could multiple log-ins be handled? Since the private keys would be stored on one device. – Alex Mar 27 '15 at 14:09
  • Hm i think you already meantioned the solution yourself. Store the private key locally and encrypt it using password-based encryption. So euch user can only access the keys/accounts he has the password for. But the mitm is still a problem. Think of how A gets the key for B: it asks the server for the pub key of B. The server can still lie, provide its own key, decrypt it and encrypt and send it to B (remember that the server also has the original Pub key of B). I am pretty sure you can not solve this if the key server and the message server are the same. – user3363866 Mar 27 '15 at 17:58
  • 1
    How would using two different servers help? In the worst case mitm could still be used to switch keys, right? How would I use two servers practically to ensure secure usage? Thank you for taking your time to help me grasp the problems with this sort of security. – Alex Mar 27 '15 at 19:06
  • 1
    Two different servers only help if they are independent. If they collude, you ' re lost again. But if only one is malicious, it does nit break secrecy. Scenario 1: key server is malicious. If A asks for the public key of B, the server responds with a wrong one, potentielly its own. A will encrypt the message with a wrong key which the key server could read, but uploads the msg to the message server which is assumed to be honestly and therefore the key server can not read the msg. On the other hand, B can not read the message, so this can be seen as a denial of service. – user3363866 Mar 27 '15 at 19:12
  • 1
    Scenario 2: msg server is malicious. Then A encrypts for B. The msg server sees the ciphertext but can not decrypt/read since it does not have the secret key. So using 2 independent servers means 2 instead of 1 need to be evil to break the secrecy =) – user3363866 Mar 27 '15 at 19:14
  • Now I understand it. Thank you for the clear explanation. I obviously have some reading up to do before I continue on - which in turn is what I want - to educate myself on this topic! The answer is accepted for the main answer as well as the comments above. – Alex Mar 27 '15 at 19:17
  • 1
    Last question. If I encrypt the private key with a key derived from a password, can I store it on a server for the user to be able to log in on other devices - securely that is? – Alex Mar 27 '15 at 19:41
  • Formally, this should be possible if you use a sufficiently secure cipher (e.g CPA secure). Intuitively, uploading the secret key is not a good idea. If you prefer, you can find other possibilities, like for example deriving a key directly from a password (see key derivation functions). – user3363866 Mar 27 '15 at 21:37
0

If you want to guarantee full confidentiality, i.e. that the message can only be read by the recipient, you will want to use end-to-end encryption. Separate key and message servers are well and good, but all it takes is a court order or two to get them to collude.

Authenticity is at least as important. Having the best confidentiality in the world won't protect you from the equivalent of a 3way prank call. The only way to be absolutely sure is to exchange keys in person. As an example, the Signal messaging app does this with "safety numbers".

Fax
  • 175
  • 6