13

I'm developing a mobile application for Android and iOs. What is best practice when it comes to data encryption within the mobile application which will be sent to a web service?

Basically I will generate a string which consists of some parameters like GPS and time. This string needs to be encrypted and then be passed to a web service.

I have considered to do it with asymmetric encryption. Encrypt the string with the public key (which has to be hardcoded?) and decrypt with private key. Because every application can be reverse engineered this is not secure at all. After finding the hardcoded public key and the string generating function it's easy to forge whatever you want.

Any input is highly appreciated.

EDIT: A clearer approach of my question: A function of my application will generate a string and another function will encrypt this string, which will be sent to a server. How can I prevent a self crafted string to be passed to the encryption function after reverse engineering my application? In other words, can I ensure with an encryption technique that data sent by my mobile application to a server is not crafted by someone else?

4
  • Please advise us of the name of your application so that we could never install it. If I want to be trackable, I simply put batteries back into my cellphone... Commented Feb 17, 2013 at 1:10
  • I suspected such a comment. With the GPS data I want to make sure that the user is in the predefined area when he wants to send something to the web service. Otherwise the data is discarded respectively not accepted by the server.
    – niklr
    Commented Feb 17, 2013 at 11:09
  • 1
    Your threat model as stated is incomplete: you said you want to encrypt the string, but the real fear for you is somebody reverse-engineering the app and sending fake coordinates. Please update your question AND its title. Have to comment that with the phone in physical possession of the attacker achieving this solely in software of the gadget is pretty much impossible (Evil Maid once again). You have to provide a separate way of identifying the location. TDOA, cell tower ID, whatever... Commented Feb 17, 2013 at 11:47
  • 1
    What did you end up doing?
    – kouton
    Commented Apr 27, 2014 at 3:49

3 Answers 3

21

You can't. This is a fundamental principle of general purpose computing.

You're running into Shannon's maxim:

The enemy knows the system. One ought design systems under the assumption that the enemy will immediately gain full familiarity with them.

Just to make my point completely clear: you're giving someone a car, and asking them to only ever drive to one particular place. Nothing stops them from deciding to go somewhere else - you're relying on them adhering to your request.

If your security mechanism hinges on the hope that someone won't look at your executable and discover your encryption method / embedded keys, then it is not a security mechanism; it is an obscurity mechanism.

From what I can tell, you're trying to enforce that users are within a specified area via GPS coordinates, and also want to ensure that they don't spoof those coordinates. This cannot be done on a general purpose computing platform such as a smartphone. Let's look at the technology stack:

  • Your webapp sits in "the cloud" somewhere. You control this entirely.
  • Your app sits on a phone. You have minimal control over this, if any. Possible attack vectors include reverse engineering, app modification, direct webapp requests, memory editing, etc.
  • The smartphone OS (e.g. Android or iOS) runs on the device. You have no control over this. This is responsible for communicating with the GPS device and translating data into usable coordinates. Possible attack vectors include: fake GPS coordinates via test panel (most phones have this feature), modified GPS driver, hooked GPS APIs, etc.
  • The GPS module is inside the device. You have no control over this. The GPS module is responsible for communicating with GPS satellites and relaying the data to the CPU via a standard bus. Possible attack vectors include: man-in-the-middle on the bus, replacement fake GPS module, fake GPS satellite signal from software defined radio, etc.

So you cannot enforce that the GPS coordinates you receive into your webapp are correct, since they might have been tampered with at the app level, the OS level, the hardware level, or even the GPS signal level. Or, barring all that, someone might just skip the phone entirely and manually send requests to your webapp containing phony data!

The solution is to accept the risk or change your security model.

4

You should always use SSL.

SSL has a public key built in, and provides for "authentication", meaning it ensures that the server you're communicating with is actually the webservice you want, and not some impostor.

Since you don't indicate otherwise, or any other need you have, I think SSL will solve all your concerns about sending data to a server and securing it in transit.


Update

Based on your updated requirements in the comments, I understand you want to prevent spoofing of the GPS data sent to your webservice.

If you have no control over the device (administrative or otherwise) what @Polynomial says is correct. If you are creating a closed system, embedded, or are in a corporation you may have more options.

Suppose you have full control of every phone your application will run on. That means locking the phone down, maintaining exclusive control of the admin password and never give it to the end users.

Next, you can assign each device a unique key to encrypt the data to be sent to a web service.

If a given phone is compromised, you will be able to determine which device it was based on the key used.

4
  • No, I think my question was not clear enough. A function of my application will generate a string and another function will encrypt this string, which will be sent to a server. How can I prevent a self crafted string to be passed to the encryption function after reverse engineering my application?
    – niklr
    Commented Feb 17, 2013 at 0:04
  • 3
    What is the purpose of this string? Why does it need to be encrypted this way? Commented Feb 17, 2013 at 0:15
  • When (not if) your application is reverse-engineered, you will have zero control over what string-generation function, or even what encryption function, will be used. You can trust your own servers. You can trust an end user after they prove they are who they say they are beyond a reasonable doubt. You can never trust the client software, or the machine it runs on.
    – KeithS
    Commented Feb 18, 2013 at 20:50
  • @KeithS Correction: You can never FULLY trust the client machine. Trust and the risk of breaching the trust is relative to every situation. If this software isn't for consumers, the contractual employer - employee (or contractor) agreement can also deter this and increase trust. Not to mention physical controls on the device (soldered USB port, tamper evident case, security screws, etc.) and physical device audits can play a significant role. Commented Feb 18, 2013 at 23:25
4

The best practice depends on the exact usage.

What I gather from your question is that you have an app which sends you GPS data and time, like a "footprint" application. You want to ensure that you are not being fed false data, and so you want to ensure that the data is coming from your real client and not a fake.

Well, unfortunately as other answers have stated, that is impossible. Given the APK file for your app, someone can quite feasibly decompile it into Java source code, possibly not as elegant as your own source, but definitely workable. They can then use your code to build their own app, that communicates with yours in exactly the way you expect, and use it to feed you false data.

Therefore, whatever scheme you use for data transport should never trust the client. It should instead trust the user.

Consider this solution; your app server is signed with a trusted public-key certificate (it could, in this circumstance, be trusted for the sole reason that your application knows the exact certificate it should be given; this is called "certificate pinning" and it works whether you got the certificate signed by a global CA or not). Upon request, it presents this certificate to whomever asks for it; it's public information, you could plaster this thing on every hacker forum on the Internet and it would be no less secure. Your client uses this certificate to negotiate a secure communications tunnel; this is pretty standard stuff.

Now, you have confidentiality. You need authenticity; it doesn't matter that nobody else can listen to the conversation between the two of you if you don't know for sure who's on the other end. So, once the channel is open, the next thing you expect is an authentication request containing user credentials. You should reject any request to send GPS data if the session has not been authenticated. The credentials the user supplies in such a request could be their username and password, their phone's IMEI or MAC address, the 10-digit code from a crypto key fob, whatever you think is necessary to properly ensure that only a particular user could be able to provide those credentials.

Once you have those credentials and have verified that they match expectations, however you want to do that, you send them back an "authentication token". This is as simple as a random number distinct from that used for any other open session. A V4 GUID's a pretty good choice as well. This identifier will be required as part of any request to send or receive data on this channel during this session, it will only be accepted on this particular channel, and only as long as this unique session is open.

Once all this is set up, any service call that was made over that session's secure channel that includes the correct authentication token can generally be trusted. You should probably include one more thing, which is a measure to guard against replay attacks. An attacker doesn't have to know exactly what's being sent back and forth to mess you up by simply repeating what has already been said. So, to ensure that your system only deals with a unique message one time no matter how many times it's sent, each message should include a nonce, a unique value used one time. A simple sequence counter value, forming part of the request structure and encrypted by the secure channel, should suffice for this; then, all you have to do is ignore any message whose sequence number isn't the next one you expect to receive from the client (there can be some fault tolerance inherent in this, but never accept the same type of service request from the same client with the same sequence number twice).

You must log in to answer this question.

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