The team of developers I am part of is trying to develop a safe way to exchange sensitive data between a server and mobile devices.

We have come up with the following algorithm:

  1. Device generates private RSA key, and sends the public key to server.

  2. Server generates unique to user AES key and uses the RSA public key to encrypt it and send it back to device.

  3. Device gets the AES key. Uses it to encrypt password and username and sends it to the server.

  4. Server decrypts the username and password. If there is a match, the AES key is used for secure communication for X amount of time or until log-out. Else, the process must be restarted.

Is it safe enough? Are there ways it can be improved? What are the faults?

Edit: After reading the comments, what is a safer alternative and why?

Edit2: Ok, i get it. I won't use my own implementation, will find something already tried and proven.

  • 44
    PLEASE DON'T ROLL YOUR OWN CRYPTO / SECURITY. What's wrong with SRP and TLS? – SEJPM Jul 14 '15 at 12:04
  • 4
    We all are new to cryptography and creating our own crypto protocol seems like a good ideea – Adrian Sicaru Jul 14 '15 at 12:05
  • 43
    We all are new to cryptography and creating our own crypto protocol seems like a good ideea - That shocked me alot. You don't know what to do in crypto and because of this you want to make your own protocol!? (hint: really bad idea) – SEJPM Jul 14 '15 at 12:07
  • 3
    Adrian - please read: meta.security.stackexchange.com/a/915/485 – Rory Alsop Jul 14 '15 at 12:10
  • 7
    Also, keep this quote in mind: "If you think cryptography is the solution to your problem, then you don't understand cryptography and you don't understand your problem" - Roger Needham and Butler Lampson – mikeazo Jul 14 '15 at 15:40

All of the weaknesses in your protocol can be summed up as "use SSL" or even "use SSL, dammit !".

In more details:

  • All the protocol is of course vulnerable to impersonation, specifically the double impersonation that is also known as Man-in-the-Middle attack.
  • Similarly, if any of potential attackers that can eavesdrop on the line decides to do a modification of the data in transit, then he can, and your client and server will be none the wiser.
  • Experience shows that saying "encrypt all the data with that key" and then doing it correctly is awfully complex. SSL itself took almost 15 years to do that, and many implementations are still not up to it. Padding oracles, predictable IV, MAC verification timing, verified closure, protection against resequencing and replay of packets...

As an overall assessment: don't do that.

  • 2
    Surely you mean TLS and not SSL. Wikipedia: Transport Layer Security: SSL 1.0, 2.0 and 3.0 "As of 2014 the 3.0 version of SSL is considered insecure..." "SSL 2.0 is deprecated..." "SSL 3.0 is deprecated..." – a CVn Jul 14 '15 at 12:22
  • 25
    I use "SSL" to designate the family of protocols that goes from SSL 3.0 to TLS 1.2. The usual "SSL vs TLS" terminology is not good; see this for more details. – Thomas Pornin Jul 14 '15 at 12:25
  • 1
    Fair enough, there. But in this particular instance, maybe you want to be slightly more explicit and say "use a modern/standardized variant of SSL"? Anyway, minor detail in the grand scheme of things. – a CVn Jul 14 '15 at 12:28
  • Using SSL doesn't address the question of how to validate a password. As we know password validation can be done very insecurely, even if the SSL encrypted communication isn't broken. For a new systems which are not bound by backward compatibility requirements I would recommend using a password validation method in which the server never sees the password in clear. Your answer could be improved if you would include a recommendation of a standard password validation method with that property. – kasperd Jul 14 '15 at 20:21
  • 1
    Seeing the password in clear on the server side is not an issue as long as there are guarantees that the client is talking to the genuine server (the server certificate in SSL is used for that), and the server computes a strong password hash on incoming passwords, to compare with a stored value (the usual recommendation for that password hash is bcrypt, NOT any homemade construction, of course). A more advanced protocol would make the client compute the bulk of the bcrypt value, but this would work only with computationally powerful clients. – Thomas Pornin Jul 14 '15 at 20:28

No this protocol isn't safe.

As already mentioned in the comments:

Don't roll your own crypto. Chances are you're getting it wrong. Especially if you admit that you don't really know what you're doing.

First, you seem to have standard problems for which there are already standard protocols, which have nice properties and security proofs. The protocol for the data transmission should be TLS v1.2 (or newer). You should use a library (like NSS, GnuTLS or OpenSSL for this). For password authentication the best choice you have is to use SRP or TLS-SRP. However if you really can't afford SRP (which should be your first choice) you can still follow this paper.
So far for the improvements.

Now for the flaws of your protocol:

  1. It's vulnerable to Man-in-the-middle attacks. If an attacker sits in-between the device and the server, he can fish the public key and replace it with his own. In response he'd know the AES key and could decrypt all the data.
  2. You don't mention integrity / authenticity of the data. It sounds like you want to use ECB mode for AES (which you really don't want to use), you'd be a lot better off with AES-GCM for the bulk-encryption. You also don't mention how RSA is to be used, RSA-OAEP should be your choice (and not textbook RSA). However I assume you'd have done this with your implementation.
  3. You put a really large workload on the device. The device needs to generate a new private RSA key with every connection, which is a highly computing-intense task. You should rather consider using ECDH key exchange.
  4. For the verification of the passwords to work, you either need the server to store the passwords in plaintext or to hash them himself, which may enable DoS attacks on the server. And in case a man-in-the-middle attack takes place, the plain passwords will be revealed to an attacker, which may cause serious harm to your users (as they may re-use their passwords across sites...)
  • As for (4), I'm not sure which is worse: storing passwords in plain text, or (at least in the eyes of an active attacker essentially, and certainly for the server) sending them in plain text... – a CVn Jul 14 '15 at 12:25
  • @MichaelKjörling, added the reovery of passwords in case of an active attack. Thank you. – SEJPM Jul 14 '15 at 12:31
  1. Device generates private RSA key, and sends the public key to server.

  2. Server generates unique to user AES key and uses the RSA public key to encrypt it and send it back to device.

  3. Device gets the AES key. Uses it to encrypt password and username and sends it to the server.

Anonymous key exchange.

There is no authentication. Your key exchange is encrypted, but not authenticated. This is bad.

If there is an active Man-in-the-Middle, then you have no way of detecting this. This active MitM can just pretend to the client that he is the server. And pretend to the server, that he is the client.

-> Don't do it. @SEJPM is right with his comment. Use established crypto systems. Like TLS with certificates or TLS with SRP.


that's the way i use to do rsa /aes combination

  1. client generate a random aes key
  2. use the aes key to encrypt the data you need (rsa take longer time and have length limitation, so better use aes to do encrypt)
  3. use the public key to encrypt the aes key
  4. pass the encrypted data and the aes key encrypted by rsa public key to server
  5. when server receive, decrypt that aes key by private key and then decrypt the attached data by the decrypted aes key

It's pretty good but I would do this in an easier manner which I think is more secure and similar to what you thought of.

Since the communication is client-server:

  1. Mobile client generates key using PRNG
  2. Client sends step 1 key using server public key (only server has private to decrypt)
  3. Client encrypts user/password with step 1 key and sends to server
  4. If user/password are verified - server returns new key for data encryption, encrypted with step 1 key

-. Please do step 2 - 4 over TLS if possible

--. Change keys every X iterations (enforce on client and server)

---. Client must trust server certificate to prevent MITM/impersonation

  • "Please do the key-exchange over TLS". Well ... this is secure. But why exactly do you need your own key-exchange then? – SEJPM Jul 14 '15 at 12:21
  • Because he may not be able to use SSL/TLS for the data exchange or he may be using weak cipher suites. – Erez Jul 14 '15 at 12:22
  • 6
    Why would he be able to use SSL to to authenticate but not to transmit data? – Cthulhu Jul 14 '15 at 14:50
  • different servers, topology dependent – Erez Jul 15 '15 at 8:32

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.