I have an app that sends an encrypted message to the server, with the sender and recipient username attached. The usernames are each linked to a unique device ID that allows messages to be sent to them through the Google Cloud Messaging service.

My problem is that I'm not sure what the best way is to prevent anyone from just forging messages to the server and writing any possible username into the sender field.

I was hoping that I could just use a secret key stored within the app's code which is the same as a key stored on the server corresponding to a specific user, but I've since found this key would be prone to being discovered through reverse engineering the app.

So now the only apparent solution to me is to implement a password based system that generates a limited time session key on the server that is fetched by the client after submitting the correct password, and then sent along with each subsequent message.

However, I would rather avoid this kind of system as I want to keep the app as simple as possible, and avoid having to implement forgotten password systems and such.

Are there any other ways in which I could ensure messages are authentic?


From the cryptographic point of view, if one user A must be able to do something that another user B cannot (e.g. sending a message with "A" as sender's name), then there must be some value that A knows but B does not. That kind of secret value is called a key, although there are other terminologies (e.g. "password" when the secret is stored in a human brain).

Hiding keys within application code has two major drawbacks:

  • They can be recovered through reverse-engineering.
  • They are not user-specific.

However, in your case, you want a user-specific secret value: each user has his own key, with which his messages are authenticated. Therefore, the user's key cannot be hard-coded in the compiled application code; however, it may be stored as a file on the user's device. Reverse-engineering is here a non-issue: by reverse-engineering his own app installation, the user may learn his own key, not the key of somebody else.

The important point here: such a key authenticates the user, not the device. Making sure that a given message comes from a specific device, and sent by "your unmodified app" and not other code, is nigh impossible, since the said device is physically in the hands of the user, and is not tamper-resistant. To get such kind of guarantee, you need a device which is able to fight back against its owner, e.g. a smart card. Mobile phone billing works, both practically and legally, because the user cannot break into his own SIM card. You cannot have this model with an app which is software-only on non-shielded hardware (the phone itself).

However, as long as you want to authenticate users, not devices, then a user-specific key is fine.

Then comes the tricky part: authentication is good, but who is doing it ?

If you just want your server to make sure of the identity of A, then a shared secret between A and the server S can be fine. The underlying cryptographic tool would be a MAC. However, in that case, when user A sends a message to user B through your server, the server is certain that it indeed talks to A, but B knows nothing. An evil user E, who wants to forge a fake message purportedly coming from A, may send the said message directly to B, without going through your server at all !

One solution, in that case, is to make the communication from S to B equally authenticated with the B key: this time, that's B who makes sure that what he receives from S is indeed from S. With MAC applied in both directions, for all communications between the server and any user, then you can have a reasonably secure messaging network. Of course, S is trusted: your server can betray everybody at will. But maybe this is not a problem for you.

(For end-to-end authentication, without trusting a central server, you would have to resort to asymmetric cryptography and digital signatures, and things become a good deal more complex.)

Storing a user-specific key in a file on the user device sure seems simple enough. However, sometimes, users switch devices (e.g. they buy a new phone, or they are Apple-addicts who have an iPhone and an iPad) and still want to retain their identity. This implies that the user-specific key somehow travels from one device to the user.

The scheme that you envision (storing the key on the server itself, with automatic download after password-based authentication) is valid. Be sure to do that over SSL, of course. You may combine it with a caching mechanism: the app downloads the key when it does not already has it, but then it stores it on the device.

  • Thanks, this is a great answer. I didn't consider storing the key in a file. It should now be possible to just generate a key on the server, send it back to the client (via SSL) and then store it in a file. No need for passwords. I could go on to implement a system that uses passwords, but this app is supposed to be device specific anyway rather than user account specific. – JackWoot Jan 28 '14 at 14:56

Since its an app, I assume its for mobile devices? In that case, using the well-established TLS protocol is highly recommended. It provides confidentiality, message authentication and integrity via the use of encryption and message authentication codes (MAC). It does not require any keys to be stored in your app if you purchase a public key certificate for your server. Also, there are SSL/TLS libraries available for the Android SDK and iOS.

Otherwise, if you implement your own message authentication scheme and handshaking protocol, it may not be secure enough and prone to implementation errors.

  • But then couldn't someone still just write their own message, forge the sender, and send it to the server anyway by encrypting it with the public key? And yeah, it's an Android app. – JackWoot Jan 28 '14 at 9:29
  • Mmm can we assume that the username is public and the device id is the secret? We can then securely transmit these information via tls for authentication. So the causal adversary won't be able to easily masquerade as the sender. – jingyang Jan 28 '14 at 12:37

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.