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.
Related
I'm working on an Android multi module (multiple apps) project and encountered a use case where I have to save some secret information that could be accessed by all these apps. My idea is to encrypt the secret information using a private key that is saved inside the KeyStore, and save this information in a file that I'm planning to store in the device (not external storage). My question is, would I be able to access this private key inside the KeyStore from another application and then use it to decrypt the secret information that is saved in the device?
I was looking at Android's KeyStore documentation, and if I understood it correctly, I can use the KeyStore APIs to save the cryptographic keys and use them with in the same application. But also the KeyChain documentation says I can use these cryptographic keys across multiple apps with in the system. I'm quite confused about how I can combine these two APIs and make it work for my use case. Any help is appreciated. Thank you.
My idea is to encrypt the secret information using a private key
You encrypt with a public key, never with the private key. The private key is used for decryption.
If you create public keys for all the apps then you can decrypt with individual private keys for these apps. Of course you'd have to trust these apps and the public key pair of each app in advance; I'm not familiar enough with your setup to make any recommendations in that regard.
To be honest the KeyChain API seems more about TLS authentication than anything else and I don't think it fits your use case. The API of the choosePrivateKeyAlias for instance only talks about authentication and a server requesting a key chain.
Key stores can be can in principle be distributed. Or course, to access / decrypt them you'd still need a key distributed within each app. You can share the information for specific signed applications only it seems. Possibly just the security of sharing the data privately without encryption already fulfills your use case? Key management is tricky, after all.
Caveat: I'm not terribly well known with the Android security model; hopefully my general knowledge of cryptography & security steers you in the right direction.
There is android:sharedUserId property. From the doc:
Apps with the same user ID can access each other's data and, if desired, run in the same process.
Unfortunately, it was deprecated in API 29 without proper replacement.
Since Android 4.3, Android has its own keystore where I can store keys and use them later for encryption/decryption.
It is said here and here that each key can only be retrieved by its owner and not even root can get it.
My question is:
Couldn't I write a program that would switch my uid to the owner of the key, retrieve it, and then use it to decrypt data I shouldn't have access to?
Edit: Added citation to keystore doc.
It is true that normally a key can only be retrieved by the user that stored it.
See e.g.: http://nelenkov.blogspot.se/2011/11/using-ics-keychain-api.html
If a device is rooted, the keys still cannot be retrieved unless the attacker also has the password.
If the attacker has rooted the device and has the password or the device is unlocked, it's game over.
Its been a while since the original post, so the content in the links may have changed.
The first link doesn't mention anything about root. But it does mention:
If the Android OS is compromised or an attacker can read the device's internal storage, the attacker may be able to use any app's Android Keystore keys on the Android device, but not extract them from the device.
This may sound contradictive: how can an attacker use the KeyStore keys without "extract[ing] them from the device"? This gets to the core of what the Android KeyStore is for.
One of the major properties about the Android KeyStore is that it is separate from the OS, through the use of Trusted Execution Environment (TEE). So, if an attacker could compromise the OS, then they couldn't compromise the contents of the KeyStore (this isn't true in the case of a software-backed KeyStore). The KeyStore securely stores the keys and (at the request of the OS) encrypts/decrypts data using those keys. If an attacker is able to compromise the OS, then the attacker is also able to request the KeyStore to decrypt previously encrypted data on the device. The important property is that the attacker never actually "sees" the keys themselves; meaning the attacker cannot decrypt data that is stored off the device.
The second link says:
This provides a place to create or store private keys that cannot be exported off the device, even in the event of a root or kernel compromise.
This echoes back what I said before. A malicious program with root is unable to physically "export" the keys off the device. However, this does not mean that the program is unable to request the KeyStore to decrypt data stored on the device.
To answer your question:
Couldn't I write a program that would switch my uid to the owner of the key, retrieve it, and then use it to decrypt data I shouldn't have access to?
With root, you can essentially do anything that is not restricted in hardware. There is some exception to this with SELinux. But otherwise, I don't see a reason why root can't do so. This is backed by the answers to:
Is android keystore still vulnerable if root access is received?
An application with root access has full control over the system and can do whatever it wants to do because it can override all (DAC type *) security restrictions. So the short answer is "yes".
How to crack (get secret from) Android Keystore System
Any app with root privileges can impersonate other apps and have their sensitive data decrypted or signed by the keystore by issuing a legitimate request on behalf of other apps and system.
Android - What are the practical security benefits of using a hardware-backed keystore vs software-only keystore vs no keystore
The purpose of a key store is not to restrict access to an application or application data, it's purpose is to protect the credential from being exposed during use. Since a key store will willingly leverage its knowledge to encrypt data or access sensitive application information, it's not really a challenge for an attacker to leverage as you pointed out in many of your breakdowns across all three types.
Android Kernel Security
Encrypting data with a key stored on-device does not protect the application data from root users. Applications can add a layer of data protection using encryption with a key stored off-device, such as on a server or a user password. This approach can provide temporary protection while the key is not present, but at some point the key must be provided to the application and it then becomes accessible to root users.
The last point is meant for a more generic treatment of the problem. If an attacker has root, it is essentially impossible to defend against. Encryption won't stop the attacker because either the attacker can directly find the encryption key on the device, request a hardware backed solution to decrypt the data for it, or wait for the application to decrypt the data itself and then root can dump the process's memory and get access to the unencrypted data.
"Couldn't I write a program that would switch my uid to the owner of the key, retrieve it, and then use it to decrypt data I shouldn't have access to?"
UIDs are assigned to individual applications at install time. An Android application cannot change its UID.
Newer version of Android are using a Hardware Keystore or StrongBox Keymaster. I.e. a compromised device can use the key, but not extract the key material. The whole secure computation is done in a dedicated secure environment.
Since Android 6 a hardware key store is offered, e.g. using a TEE (trusted execution environment, i.e. special isolated CPU area), since Android 9 StrongBox which would be a dedicated secure element, i.e. special chip.
The key must be stored in a way to support this, i.e. the developer has to pay attention storing the key securely by.
The Android Compatibility Definition for Android 9 is requiring at least a TEE implementation.
Depending on your phone when looking into "Settings -> Security -> Encryption & details -> Storage type" a high level information can be seen, if the phone supports any kind of these features.
I am looking into making my user data secure for android. I come across keyczar. I found the android-keyczar-demo provided by Kenny Root who gives talk on android security at google-IO. However I have a nagging question. Since the keys are packaged in the app, isn't it the case that malicious user can also use that key to decrypt the sensitive data? From keyczar doc, keyczarTool is a command-line tool to create the keys, so it seems that it is not meant to be packaged in the app? I have noticed that keyczar's key can be password protected. However it comes back to hard coding the password in the source code. What am I missing to understand here?
What you are missing is that you can't semantically keep the key secret from your users if you also want those same users to be able to decrypt. That's why DRM will never work.
The reason keyczar has the keytool is that an important part of security is changing your key over time, and so keyczar provides a way to rotate your keys without breaking functionality.
The PBE keysets are there so that a user can enter a password to decrypt, it is definitely not intended to be hard coded. That way given a keyset for an app, you can protect the data from an adversary while providing decryption to your user, by requiring your user enter a password. (Unfortunately this feature is only present in the C++, Go, and C# versions of keyczar--not currently in the java version).
Also if you don't want every user to have the same key you don't have to include the keyset with your app, you could also generate it installation. But encryption in the mobile space is difficult, it's hard to say without knowing what you are trying to do, if it's possible for you to secure what you want or if keyczar is the right fit.
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.