In my application, upon user successful authentication using OAuth I need to store the access token returned by the REST API. I was thinking of using the keystore to store this token for further use in the application. But so far I havent seen an implementation which stores already generated keys using android keystore APIs. Is there any example or code snippet which stores already generated tokens.
Also if I use keystore to store the access tokens, can the rooted phone users gain access to these tokens?
Thanks.
The following blog post provides a very good explanation on how to go about doing this.
http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html
Also it should not matter if a rooted phone user can gain access to these tokens if they are encrypted. Fortunately, Android's system keystore daemon encrypts keys using AES.
Related
Is there an equivalent to iOS's Keychain on Android?
My understanding of the Preferences API is that it is not encrypted. For my application it doesn't matter whether these credentials are persisted across devices (i.e. a different use-case to iPhone-like Keychain in Android?)
I also looked at the KeyStore API but it seems to leave the actual storage of user credentials up to the application developer.
Short answer, there isn't one. But you can expect the filesystem to be secure.
Each app operates under a different user, and the filesystem used to store app data is secured by normal UNIX user permissions. So each app's file access is sandboxed by default. The filesystem also may be encrypted.
This page from the developer's site explains it better: http://developer.android.com/guide/topics/security/security.html
Actually there is:
By integrating Smart Lock for Passwords into your Android app, you can
automatically sign users in to your app using the credentials they
have saved. Users can save both username-password credentials and
federated identity provider credentials.
Integrate Smart Lock for Passwords into your app by using the
Credentials API to retrieve saved credentials on sign-in. Use
successfully retrieved credentials to sign the user in, or use the
Credentials API to rapidly on-board new users by partially completing
your app's sign in or sign up form. Prompt users after sign-in or
sign-up to store their credentials for future automatic
authentication.
https://developers.google.com/identity/smartlock-passwords/android/
Expanding upon #DJPlayer's answer:
Some relevant articles. The third includes a github app that demonstrates using the keystore provider to generate keys and then encrypt strings.
Android Keystore System
Where is the best place to store a password in your Android app?
How to use the Android Keystore to store passwords and other sensitive information
Also see Android Storage Options for ways to store the encrypted password - my recommendation is Shared Preferences.
Note that according to the second article with root access and a bit of knowledge of how your app uses the keystore (which might be obtainable from decompiling your apk), it's possible to hijack the private key and use it to decrypt encrypted material (ex: the persisted password)
http://developer.android.com/reference/android/security/KeyChain.html
Keychain for OS 4.0
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
What is the best place to store API keys, Database encryption keys etc. in the app code so that nobody can get it by decompiling the code ? I used proguard to obfuscate the code but it didn't work on Strings.
There is no way to store them in the app. The app can be decompiled or executed on a modified device which provides more access to the app's memory, or the app can be modified by the attacker to add additional logging of network or storage/database traffic, etc.
For authenticating to servers, your app should probably obtain auth tokens (or similar) by exchanging user-entered credentials for such auth tokens or by obtaining these auth tokens from AccountManager or similar APIs. You could also use SafetyNet Attest API (https://developer.android.com/training/safetynet/index.html) to attest to your servers that it is your app signed with your signing key which is making the request.
For database encryption, the app could generate a random encryption key on-device, either linked to user-entered credentials or stored in Android Keystore, or simply rely on protections offered by Android to apps. It depends on your threat model (i.e., why do you think you need to encrypt databases?)
Adding the AWS access key and secret key directly in app code is definitely not a good approach, primarily because the app resides on the users device (unlike server side code), and can be reverse engineered to get the credentials, which can then be misused.
Though I find this information everywhere, but am unable to find a definitive solution to this problem. What are my options? I read about the token vending machine architecture for temporary credentials, but I am not convinced that it is any better. If I can reverse engineer the secret key, then I can reverse engineer the code which requests for temporary credentials. And once I have a set of temporary credentials to access S3, I am as good as if I had the key. I can request the temporary credentials again and again, even if they expire pretty quickly. To summarize, if an app can do something, I can do the same as a malicious user. If anything, the TVM can be a bit better at management (rotating credentials, and changing key in case of breach, etc.). Please note we can put the same access restrictions on the secret key, as we plan to do in case of TVM temporary credentials.
Additionally, if Amazon doesn't want people to use the secret key directly in the App, why don't they block it in their SDK, and enforce TVM or the correct solution. If you will leave a path, people are going to use it. I read several articles like these, and wonder why?: http://blog.rajbala.com/post/81038397871/amazon-is-downloading-apps-from-google-play-and
I am primarily from web background, so my understanding of this may be a bit flawed. Please help me understand if this is better, and whether there is a perfect (or may be good) solution available to this problem.
PS: Is there a rails implementation of TVM?
Embedding S3 keys in App code is very risky. Anyone can easily get that key from your app code (no reverse engineering or high skill set required), even if that is stored encrypted it is still compromised just that someone need to try harder (depending on how do you encrypt).
I hope that you understand the advantages of using temporary credentials to access Amazon (S3 etc) resources (mainly security + some others like no app update etc). I think you are more confused about the process to get the temporary credentials from TVM and how that is safer than embedding keys in code.
Every client using TVM first need to register with the TVM server implementation hosted by you. The communication between App (using TVM client) and TVM server is over SSL.
First the app register with TVM by providing UUID and a secret key. Please note that the secret key is not embedded in App code (which I think is main reason for your confusion) but generated randomly (using SecRandomCopyBytes which generates an array of cryptographically secure random bytes) at the time of registration (and hex encoded).
Once the device is registered successfully with TVM, the client TVM store the generated UDID and secret key in a storage called Keychain in iOS and Shared Preferences in Android. The keychain in iOS is the shared storage provided by iOS to securely (encrypted) store information (mainly keys, password etc).
After registration and UDID/Secret Key storage, App can get the token from TVM by sending the UDID, cryptographic signature, and a timestamp. The cryptographic signature is an HMAC hash generated from the timestamp using the secret key. The TVM can use the UDID to lookup the secret key and uses it to verify the signature. The TVM then responds by sending back temporary credentials, which are encrypted using the secret key (uses AES). The application decrypts the temporary credentials using the key and can then use them to access any AWS services for which the temporary credentials are authorized. Eventually, the expiration time of these temporary credentials will be reached, at which point the application can get the fresh temporary credentials, if required.
I am not sure how signed URLs relate to TVM, because I don't understand the concepts 100% but signed URLs really solved the problem for me. I needed a mechanism that would feed web app and mobile app data without allowing for misuse of the credentials. Putting the key in the code is indeed a very bad idea as it may generate a huge bill for the company.
After 3 days of extensive research, I found a simple and, what seems to be, a reliable and relatively safe solution: signed URLs. The idea is, that a very light-weight back-end can generate a temporary URL that will grant the user access to the specific resource for a limited time. So the idea is simple:
the user asks our back-end with a Rest call that he wants a specific resource
the back-end is already authorized with AWS S3
the back-end generates a temporary URL for the user and sends it in the Rest response
the user uses the URL to fetch the data directly from the AWS
A plug-and-play Python implementation can be found here and with a slight modification that I had to use: here.
Of course one more thing to figure out would be how do we authorize the user before we know that we can grant it the URL but that's another pair of shoes.
You should ideally use Cognito Identity for achieving this along with appropriate policies. It should be used with S3TransferUtility and S3TransferManager in iOS and Android SDKs. That would allow for background uploads and downloads as well. Cognito vends temporary credentials for access to AWS resources and is free. Also, you could federate it using UserPools or providers like Google, Facebook if you want secure access.
Thanks,
Rohan
Is there an equivalent to iOS's Keychain on Android?
My understanding of the Preferences API is that it is not encrypted. For my application it doesn't matter whether these credentials are persisted across devices (i.e. a different use-case to iPhone-like Keychain in Android?)
I also looked at the KeyStore API but it seems to leave the actual storage of user credentials up to the application developer.
Short answer, there isn't one. But you can expect the filesystem to be secure.
Each app operates under a different user, and the filesystem used to store app data is secured by normal UNIX user permissions. So each app's file access is sandboxed by default. The filesystem also may be encrypted.
This page from the developer's site explains it better: http://developer.android.com/guide/topics/security/security.html
Actually there is:
By integrating Smart Lock for Passwords into your Android app, you can
automatically sign users in to your app using the credentials they
have saved. Users can save both username-password credentials and
federated identity provider credentials.
Integrate Smart Lock for Passwords into your app by using the
Credentials API to retrieve saved credentials on sign-in. Use
successfully retrieved credentials to sign the user in, or use the
Credentials API to rapidly on-board new users by partially completing
your app's sign in or sign up form. Prompt users after sign-in or
sign-up to store their credentials for future automatic
authentication.
https://developers.google.com/identity/smartlock-passwords/android/
Expanding upon #DJPlayer's answer:
Some relevant articles. The third includes a github app that demonstrates using the keystore provider to generate keys and then encrypt strings.
Android Keystore System
Where is the best place to store a password in your Android app?
How to use the Android Keystore to store passwords and other sensitive information
Also see Android Storage Options for ways to store the encrypted password - my recommendation is Shared Preferences.
Note that according to the second article with root access and a bit of knowledge of how your app uses the keystore (which might be obtainable from decompiling your apk), it's possible to hijack the private key and use it to decrypt encrypted material (ex: the persisted password)
http://developer.android.com/reference/android/security/KeyChain.html
Keychain for OS 4.0