I have an android app which is receiving data from a php page using HTTP get/post request. I'm encrypting the data at server side and decrypting in android. I'm using AES 128bit Encryption, I have hardcoded the strings key and iv in the android side. If anyone reverse engineers my apk, they can get the key and iv easily. Is there any way I can store these 2 strings securely in the apk.
Please help
You can use Android Keystore Keystore provider feature that was introduced in Android 4.3 (API level 18).
The Android Keystore system lets you store private keys in a container to make it more difficult to extract from the device. Once keys are in the keystore, they can be used for cryptographic operations with the private key material remaining non-exportable.
https://developer.android.com/training/articles/keystore.html#UsingAndroidKeyStore
No, that would be akin to solving the DRM problem.
You can of course hide the key in plain sight, for instance using the answer of Alireza but it's impossible to secure the key without controlling the devices it is stored in.
You can of course implement your own transport mode security: that way you do not have to have a secret key in your APK (just a trusted public key or certificate).
However, the quick, easy and above all secure way is to use TLS. Especially when using forward secrecy (EDH_ or ECDHE_ ciphersuites) your data should be secure.
Related
I have done an Android Application using an ECC Key pair. When I have developed it last year, I wanted to create the ECC key in the Android Keystore. Unfortunately, this ECC key is used to generate a session key thanks to ECDH, and ECDH is not supported by Android Keystore (this is what I have been said here: ECDH with key in Android Key Store )
I have followed the recommendations: I have created an AES key in the Android KeyStore and I have used it to encrypt the ECC key before storing it in the SharedPreferences. Android KeyStore ensures that the AES key cannot be extracted and that only my application can use it to decrypt the ECC key.
I now have a concern for which I would like your advices:
What if someone install my application on a rooted phone, gets the APK, uncompile and modify it to print the ECC key after that has been read and decrypted? I don’t have this skill but I guess that some hackers do.
If that’s feasible, it means that the protection that I have used is not efficient.
Using ECDH is non-negotiable in my case so what solution do I have to secure my ECC key pair?
Thanks
There is no way to ensure that the key is non-extractable unless it's backed by secure hardware.
And for the rooted phone case, attacker doesn't need to modify and reinstall your APK in order to use your key. Any app on that device with the root permission can hook into your app and behaves like it. Even in trusted environment they can use your hardware backed key. Only thing they can't do is, extracting the key from the device.
You may want to read the relatively old paper about TEE and AndroidKeyStore: http://www.cs.ru.nl/~joeri/papers/spsm14.pdf . Especially "Overview of the results for Device-binding"
In order to reduce attack surface, you can:
Protect your key with the user-provided password along with the AndroidKeyStore AES key
Use SafetyNet API to check device integrity: https://developer.android.com/training/safetynet/attestation
I'm looking into ways to secure data on mobile via fingerprint verification.
The situtation on iOS seems fairly straight-forward by securing data in the Keychain via Touch.
But can something like this be done on Android where a piece of data is secured via a fingerprint? Or would we have to handle the association of data and fingerprint internally within the app?
UPDATE:
So having done a little bit more reading on this on Android I'm assuming the best way of doing this would be to encrypt the data within the app but secure the key being used with FingerprintManager and the Android Keystore?
Yes, you're heading into the right direction ;-)
Basically the Keystore is just for creating / storing key material and cannot be compared to something like the SharedPreferences. You could use the Keystore APIs to create a new cryptographic key which requires user authentication and with the generated key you could then en-/decrypt data. In order to access the key inside the Keystore the user needs to authenticate (e.g. through fingerprint authentication).
I have created a demo project for the new Keystore APIs (including fingerprint authentication) which you can find on GitHub: https://github.com/flschweiger/SafeApp
I know that a public client shouldn't use a client secret because, no matter how much you obfuscate it, it won't be protected from reverse engineering.
But, the people in charge of the service I am authenticating to don't want to/can't change it. So, I need to store the client secret and try to protect it from reverse engineering as much as I can.
So, I thought of encrypting it using at build time using gradle and store it in a file. Then, when I need it at run time I decrypt it. But now I have to solve the problem of how to store the encryption key...
I don't know much about security, so, I don't know if this can be solved, or if Android (min sdk 15) provides any mechanism for this kind of scenarios.
Any idea?
This article suggests these options, from less to more secure:
Store in cleartext
Store encrypted using a symmetric key
Using the Android Keystore
Store encrypted using asymmetric keys
Probably, using a combination of #4 and some way to univocally identify the device would be secure enough
Maybe the best option is to use NDK because it can not be decompiled, like Godfrey Nolan points here
Here is a resource I found useful that helped me to implement it link to the resource
Cheers
As you said, whatever you do, how much you try to hide your key, you can not hide it 100%.
But, if you want to make reverse engineer's work harder;
Firstly obfuscate your client (I guess you already do).
Secondly, do not put your key into the client hard-coded. Receive the key after login or user opened the application. And deliver secret key to the client over SSL. Store the secret as byte array and do not save it into the client. Just store in the memory.
These steps do not guarantee the safety of the secret key, but makes reverse engineer's job really hard.
You can also try Dexguard to obfuscate and encrypt the data. Dexguard is made by the same guy that developed proguard.
#Semih's answer was on the right track. The secret key part is what needs to be expanded upon.
The secret key is between the application and the gateway server not to the underlying services.
The gateway server is responsible for converting that key to something specific for the services.
The secret key is built using the following after the login process is complete
the server generates a key pair specific for the client logging in.
The server's public key is sent for encryption specific for the client logging in
the app will generate a key pair for it's own purposes
the app will send the public key encrypted with the server's public key
the server will validate the public key is signed with their public key.
Any future requests would involve the following
All data being sent from client to the server would be encrypted using JWT the message would be signed by the app's private key and encrypted using the server's public key.
The problem is securing #1 anyone can login and get the process started, so how would you prevent that? The only way I can think of is to do a CAPTCHA check on the login.
The solution pushes the storage of the client secrets to the server rather than on the app itself and protecting it using the app's credentials.
I have a set of rest services exposed on a public host. There are mobile apps (android, iOS and windows) that will be consuming these services. For authentication purpose, I am using a secret key that has been shared with these apps and when they hit the services, the sent key is first matched with the actual key and services are served only when the key matches. My question is that is it possible for a hacker to reverse engineer the mobile apps and obtain that secret key (so that he can misuse the web services)? If yes, then how easy is it to do that and what is the solution to this problem?
The thing is how you are saving the secret key in your app .Now there can be many things
Encrypt you key
Use progaurd
Use private but not default shared-preferences(If saving the key in preferences)
Use HTTPS instead of HTTP
These are some ways with which you can secure your key and make it difficult to reverse the process, but again nothing is completely secure but my doing these steps you can make the much difference .
For iOS use the Keychain to securely save the key. There is a Keychain in Android but it works somewhat differently.
Use https to secure the commutations of the key to the server.
Consider an authentication scheme such as CHAP.
I'm developing an application for android and I have to maintain a secure communication with a server through a pair of private and public key. Which is the safest way to storage the private key in my apk? Obviously I'm going to obfuscate the code but I want more security. I have thought the following option:
If I create a native share library with the methods for sign the transaction information, The apk only have to contain the .so file and this file is in machine code, so the decompilation could be difficult, isn't it?
any ideas?
Thanks
Store the keypair in a keystore and include the keystore as a resource in your APK. Android tends to prefer the BouncyCastle Key Store (BKS) format. Keystores are specifically designed for this purpose.
Note that you should protect the keystore with a password and your application will need to know that password to access the keystore. So, you're left with needing to ask the user for a password to access the keystore or include the password in your code (obfuscate it to make it harder for an attacker to reverse engineer). If someone is going to the trouble of reverse engineering your application to recover your encrypted keystore and the password needed to access it, including that password in a compiled native library will not present much of an additional hurdle.
However, you may not need to do this anyway. If your goal is to protect/encrypt the data in transport to/from the server, use SSL/TLS. If you're not doing client-side authentication, your server needs an SSL certificate but your client does not; the protocol takes care of generating the encryption keys for you in a safe manner. If you do want the server to authenticate the client (make it so your server only talks to your clients), you'd need to install a client-side SSL certificate with your app ... this is the private key that you're probably thinking about.
I'll also point you to Application Security for the Android Platform. This book (disclaimer: I wrote the book) has an entire chapter talking about how to design secure Android app-to-server communications, with code examples to illustrate how to implement the appropriate protections. You may want to give it a read.
First of all, in order to implement secure communication between your client application and a server, conceptually speaking, you need only the public key of the server. That allows you to establish a one-way trust relation ship with the server and to establish a secure session, in which the identity of the server is guaranteed.
While certainly the above method does not provide two-way trust (the client cannot be identified to the server), when establishing the communication channel in most applications, this level of trust is not really required.
If your requirements are to provide client authentication to the server using public/private keys then things get more complicated because if you put the key in the apk, no matter how much you obfuscate it (including embedding it in a native library) it will only slow down a dedicated nefarious user.
The only way to store the private key with the client is to encrypt it. But then you have a similar issue of where to store the decrypt key. The easiest solution is to generate a public/private key pair for the user of the client application and ask the user to provide a symmetric encryption/decryption key (which the user will always have to type in) to decrypt the private key each time the user is using the application.
The alternative would be to use some kind of dedicated cryptographic hardware device similar to a smart card that would store the private key securely but you still have the problem of authorizing your application to read the key from the device (not to mention the complication of interfacing with said device).
Now, the question you have to ask yourself is this: "Who are you trying to prevent from reading the private key?" (of course after answering the other question: "Do you really need a public/private key pair for the client").