We are developing an application that has a requirement to use HMAC when communicating with one of our back end servers.
We are required to use an algorithm which I am confident that Proguard will obfuscate enough. The issue is that the algorithm requires some initial keys that the backend service will provide to us to use in our app.
How to secure it securely on the phone? Shared Preferences is ok but then how to get it into Shared Preferences in the first place?
Related
I'm building a mobile API & library for logging analytics and have been exploring different methods of securing the API to prevent unwanted 3rd parties from logging data or intercepting user data.
My proposed method is to use public-key encryption: the user would generate the keys on the API's website, and be provided with the public/private key. The user would then manually store the key within the applications code, for example, in Android it could be a string resources file. When the app is run, the library will read the key provided by the user in code, encrypt the analytics data, and send it to the server, where it is decrypted and read.
After research I've discovered several problems with this method, most obviously that a 3rd party could de-compile the application and get the stored key (somehow?). However this seems like a lot of effort simply to get the key for analytics, which would only contain anonymous information. I also remember reading that another large developer (Twitter?) used a similar method, and changed the keys between app versions.
An alternative method could be to connect the user to the server, authenticate, then distribute keys for a session. However my application has nothing to uniquely identify and authenticate individual users (no user accounts & passwords), so I'd still need to store an identity for authenticating.
I'd really like a solution thats simple and easy for API users to implement, like copying a single encryption key, and also not bloated with network traffic for authenticating, managing sessions, distributing keys, etc. I would be interested to know how existing services such as Fabric and Firebase do it.
I'm reading about store a secretkey (to encrypt/to decrypt data) and seems there is no way achieve that. One can only increase difficult for an attacker accomplish this.
It's really like that?
What I've got so far:
Store in shared preference ( private mode ) - Rooted phone will be able to retrieve it.
NDK C/C++ native code, create .so file - Hard to decompile, but one could call this .so file and retrieve it.
A webserver to store the key, looks useless, if a have to send credentials, a malicious ware could log key taps.
Am I too paranoic?
Why do not you use Android Keystore?it is designed for this purpose
https://developer.android.com/training/articles/keystore.html
The Android Keystore system lets you store cryptographic keys in a container to make it more difficult to extract from the device
It has considerable advantages over shared preferences or private files like extraction prevention or key use authorization I do not consider storing private keys on the server
Security Features
Android Keystore system protects key material from unauthorized use. Firstly, Android Keystore mitigates unauthorized use of key material outside of the Android device by preventing extraction of the key material from application processes and from the Android device as a whole. Secondly, Android KeyStore mitigates unauthorized use of key material on the Android device by making apps specify authorized uses of their keys and then enforcing these restrictions outside of the apps' processes.
In some devices with dedicated hardware it is implemented on it. As a programmer you can know is a key is hardware-protected
The concept is similar to iOS KeyChain, but whereas IOS KeyChain can store passwords, generate and import cryptographic keys, Android KeyStore only allows to generate cryptographic secret keys by the application ( no import functions)
The keys also can be protected requiring user to unlock the device and / or presenting the fingerprint
For example, to secure a password, is possible to generate a cipher key protected with fingerprint, and use it to encrypt user's credentials that could be stored in preferences
You are correct. Most security experts will tell you there is no such thing as an absolutely secure system. The proper way to think of it is in terms of the level of resources an attacker must use to break your system.
You then balance your security measures between the value of the data and other considerations like the complexity of your solution and other costs.
To elaborate on your examples, assuming you aren't worried about the legitimate owner/user of the phone being the attacker, you can assess as follows:
Rooting a phone is a risk if an attacker gets physical possession. To assess, how valuable is the data versus the likelihood of a phone getting lost/stolen, the person who then has it caring to get the key and knowing how to root a phone.
Obscuring secret information is generally considered useless. I personally think it depends a little bit on the circumstances. Here, again, an attacker would need to root the phone, etc. The problem with obscuring secret information is it only takes one person to figure out what you've done and make that information available to completely lose the value in doing it.
If you have a key logger, what security do you have anyway?
You should look at the possibility of using a "secure element". See this post on the security Stack Exchange for some good information.
Where do I need to store the authentication token which will be submitted with each request in an Android application? I'm asking for a secure storage location, for example iphone has keychain, is there an equivalent service in Android? Is storing in shared preferences secure or not?
In Android 4.3+ there is something called AndoridKeystore which is roughly equivalent to iOS key chain. Here's a good blog write up of it and official API sample project.
In general if your create your shared preferences with Context.MODE_PRIVATE they are only accessible by your application (or other app signed by your key). However if the device is rooted they the user and any app could potentially read your app's private shared preferences.
I helped create and maintain a library called secure-preferences to obfuscate key and values that are stored in the shared preferences to make it harder for attackers and require then to reverse engineer the app (although that's not rocket science). A good alternative to secure-preferences is CWAC-prefs by Mark Murphy which is backed by SQLcipher.
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").
I want to hide some data that is entered by user in user's phone encrypted. As far as I know I can encrypt/decrypt data using a key/seed value, but if I hide the key value in code, I know it can be found somehow (e.g. decompiling the Java code).
Do you have any suggestions to make the process harder?
It is impossible to hide the key in the app such that a resourceful hacker won't be able to pull it out. You can try to obfuscate the key and make it difficult to find but it will always be do able.
See this: https://www.excelsior-usa.com/articles/java-obfuscators.html#examples
The best option would be to require your users to specify a PIN or password and to use that as the encryption key. That way if the device is lost or stolen the key is still safe and it also prevents someone from decompiling your app and getting the encryption key for all instances of your application.
One of the new features in Ice Cream Sandwich (Android 4.0) is the keychain API. From the Platform Highlights page (emphasis mine):
Android 4.0 makes it easier for applications to manage authentication
and secure sessions. A new keychain API and underlying encrypted
storage let applications store and retrieve private keys and their
corresponding certificate chains. Any application can use the keychain
API to install and store user certificates and CAs securely.
If you're doing this for username/password data, you should checkout implementing an Authenticator.
Since android does not have any secure storage on it ( at least as of 2.2), you would have to write your own.
The only way to do this really securely is to encrypt with a key derived from a user supplied password (PBKDF2/ RFc2898 being the way to that). Crypto is only as secure as your key and if you store that on the phone in anyway, then someone can find it and use it. This allows you to have the user store the key without actually remembering a large AES key.
There may be libraries that do this for android. I wrote one for windows phone that can be found here if you want some basis for how to do it.
If encryption/decryption all happens on the handset, a determined hacker will be able to crack it. You can make life harder by using obfustication, or (if appropriate for your application), adding user input into the encrypt/decrypt code.
If your application requires network connectivity, it might be worth off-loading some of the code to a server running elsewhere, so that encrypted data lives on the device, but keys are downloaded at run-time. Still not hack-proof, but it reduces risks to confidential data on a stolen device.