Android - how to get Unique key from Finger-Print Authentication? - android

I'm want to encrypt and decrypt files from SD-card using AES. In order to do it we always need a seed (usually a string which is inserted by user as a password):
public static byte[] generateKey(String password) throws Exception{
byte[] keyStart = password.getBytes("UTF-8");
KeyGenerator kgen = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG", "Crypto");
sr.setSeed(keyStart);
kgen.init(128, sr);
SecretKey skey = kgen.generateKey();
return skey.getEncoded();
}
I want to skip this step (inserting password by user) and JUST require user to Authenticate by finger-print sensor and then start Encryption process!
I wonder if there is a way that I can Obtain a unique-key for each different finger that touches finger-print sensor that can be used as SEED to create SecretKey!?
I read some questions on SO and related samples on github but I still cannot find a way to do it.
to clear the problem: I've done implementing the AES itself and completely OK with it and I just need to find a way to get unique-key from finger-print sensor after Authentication.

Updated 2019-10-14
TL;DR
No, you can't access the fingerprint. You can only get a "thumbs up" or "thumbs down" from the Biometric API. This is intentional by design.
You can, however, leverage the Android Keystore for hardware-backed cryptographic operations, and require user re-authentication to release the key. This pretty much does what you want.
The long answer
Generating a password-like seed from a fingerprint is impossible. As James K Polk commented, fingerprints vary when scanned, and they are never legibly stored directly on the device.
When a fingerprint is being enrolled, its image is temporarily stored
on secure device memory, where it is processed to generate validation
data and a fingerprint template (these are all inaccessible to the
Android OS). The raw image is then discarded. When a finger is
scanned, the image is compared to the validation data generated
before, and if it matches to a certain degree of certainty, a user is
deemed as authenticated.
Biometric operations are conducted inside of Android's Trusted Execution Environment (TEE). This is a completely isolated OS running either on a protected part of the CPU on a separate coprocessor on modern devices (SE).
It's a virtually untouchable environment with a restricted interface and hardware barriers put in place to protect against tampering with the chip and forced extraction of biometric validation data and cryptographic keys.
Solution
Going back to your original question, no, you can't get any unique finger identification. This would be inherently insecure, as any application could read the secret!
What you can do, is leverage Android's hardware-backed Keystore and require device-level authentication to release hardware-backed cryptographic keys (setUserAuthenticationRequired(true)). This means generating a random secret which is securely saved to the Keystore, requiring a finger swipe to release the key to userspace. I can't stress the word hardware-backed enough.
You have no control over which finger is can be used and whether vendor-specific implementations allow bypassing of biometrics with the device unlock pattern, for example.
Android Keystore
The Keystore's purpose is to protect cryptographic keys. Keys can only be retrieved by the application that owns them once sufficient requirements have been met, such as recent or immediate biometric authentication.
Keys can be protected against malicious extraction, and on modern devices, hardware bound, meaning they never leave the secure hardware (TEE/SE), and therefore are never exposed to your Android application. Any cryptographic operations, such as AES encryption/decryption, are securely executed outside of userspace (on secure hardware), and enrolling new fingerprints/changing the lock pattern will permanently invalidate the key. In this mode of operation, the Keystore entry merely serves as an "interface" to conduct crypto operations inside of the secure hardware, the true secret is never exposed to your application.
In summary
There is a Fingerprint/Biometric API, which is there purely for convenience, allowing you to quickly confirm an action by requiring the user to authenticate. It boils down to a "yes"/"no" answer from the TEE/SE, and vary greatly depending on the phone manufacturer!
The Keystore is a hardware-backed vault for cryptographic keys. Devices running API-level 28+ also have access to Strongbox Keymaster, if the device hardware supports it, which restricts cryptographic operations to a dedicated security CPU with more secure storage.
These features are device/vendor specific! And could be compromised/insecure! Warn users before enabling fingerprint authentication if you aren't sure about the device.
The only truly secure encryption method is prompting the user every time for the decrypt key (in this case, the mind is the hardware-backed store). Having it stored anywhere, even in live memory, is always a calculated risk.
Doing cryptography right is extremely difficult. I highly
advise that you research and try to understand the basics, and what
additional security Android has to offer, before attempting to use this in
production.

Related

What happens to the encrypted app specific data when enrolled (one) fingerprint is deleted from device?

Full Question : What happens to the encrypted app-specific data when enrolled (one) fingerprint is deleted from device and the associated cryptographic key (app-specific) stored in TEE gets permanently invalidated?
I am not an Android developer, so I do not have much coding knowledge. I was going through the working of Android Cryptography, especially the Local Authentication mechanism and have understood it this way:
In short: Following information from OWASP Mobile Security Testing Guide:
An app can use user's fingerprint to unlock itself (after a set period of inactivity).
This authentication mechanism should be supported by Cryptography to prove itself strong/secure.
We need to create a crypto Key which should be set with a property - setUserAuthenticationRequired(true), for it to be used only after fingerprint or device PIN verification.
This key could be used to sign/encrypt-decrypt the app-specific data, thereby making the whole process implement a cryptographic primitive.
The trouble in my head is with the following from Android documentation:
This only occurs for keys which are authorized to be used only if the user has been authenticated. Such keys are permanently and irreversibly invalidated once the secure lock screen is disabled (i.e., reconfigured to None, Swipe or other mode which does not authenticate the user) or when the secure lock screen is forcibly reset (e.g., by Device Admin). Additionally, keys configured to require user authentication to take place for every of the keys, are also permanently invalidated once a new fingerprint is enrolled or once no more fingerprints are enrolled.
The question is, if my device has a fingerprint enrolled and my app has set fingerprint authentication, in that case, a key would then be created and used to perform the crypto operations (say encrypt-decrypt). This encrypted data would then be stored in the app's local storage. In a case, where-in the user deletes his fingerprint from the device, as per the Android documentation, the key would get invalidated. In such a case, how would my app's encrypted data get decrypted for further usuage?? Because you need the same key to decrypt the data, which is now irreversibly invalided.
I am aware of the fallback mechanism, wherein if the fingerprint is not found, Android falls back to the PIN or Pattern device authentication. But this would again not create a new key, isn’t it? Or provide access to the same old key used by fingerprint auth (as it is invalidated).
So, what happens to the App's data? Does it get deleted? Does user has to start afresh, setting up the account and preferences?

Encrypt data with Android Keystore and user provided secret

I would like to use the Hardware Android Keystore, to safely encrypt sensitiv data and store it locally on the device. The standard implementation seems very easy and there are enough tutorials out there on how to implement it.
But the requirements I got require that a user provided secret (a user pin or password that the user has to enter) is included into the encryption of the senstive data. So that encryption/decryption of the data only works with the known user secret and not without it.
I haven't found a way to provide a user secret into the Android Keystore process.
How can I encrypt/decrypt data with the Android Keystore that needs a secret user input to actually work?
AndroidKeyStore does not provide any API to set user provided password for the generated secret. Only thing that you can do is, setting a KeyGenParameterSpec.Builder#setUserAuthenticationRequired flag to true for system provided user authentication (pin / pattern / fingerprint etc.. )
The real power of AndroidKeyStore is comes from the TEE and Secure Hardware. So that, any other option rather than using the key directly in the AndroidKeyStore should be considered as less-secure. So that, generating PBKDF2 using both user provided secret and key store encrypted secret doesn't makes your encryption more secure. Because, that new key should be managed in an application memory and is vulnerable (of course in compromised device) until you complete encryption and wipe all of the key bytes.
But in secure hardware, AndroidKeyStore doesn't even loads your keys in a memory. Every operation happens in a separated secure hardware.
If your requirement is not strictly "having one key" and "encrypt data only once", you may consider to encrypt your data twice using both of the secret from AndroidKeyStore and user key which is derived from user password.
And also, you may want to read this paper: http://www.cs.ru.nl/~joeri/papers/spsm14.pdf. In this paper, authors also mention Bouncy Castle keystore with user-provided password.

How to store secretkey in Android securely?

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.

Decrypt strings encrypted with a SecretKey, when the key is no longer accessible

I have an interesting situation here. My app stores sensitive info input by the user such as a social service account of theirs. I use a master password input by the user to generate a SecretKey, and then use AES encryption and store its SHA1 hash and the encrypted data on device, but not the master password itself or the key.
The issue is that in case the user forgets their password, there is a secret question they can answer and change the master password. So when the master pass is changed, since the previous password (and the associated SecretKey) are forever gone, I can't decrypt the stored strings and show the decrypted data to the user.
Here are the solutions I can think of:
1 - Store the password, which I have heard is totally unsafe.
2 - Store the SecretKey, but I have heard this is unsafe too.
3 - Store user data in database unencrypted, which is unsafe I guess.
4 - Wipe the entire database everytime the user forgets their password, which is silly I think.
I need a way to overcome this and I simply can't think of a secure way to pull it off.
It is crucial that this be solved for my app to fly. Any and all help is really appreciated.
Well it's a bit unfair to remove all of user's data just because they forgot a password.
Then they shouldn't be storing stuff in a container that requires a passphrase. Next, you'll argue that anyone should be able to open any wall safe using a hockey ticket stub and some chewing gum, because somebody might forget the combination for the lock.
Please note that your line of inquiry assumes that the approach described in your opening paragraph is the correct way to build the app that has the security characteristics that you desire.
For example, the right answer to meet your requirements is to not encrypt the data at all, but instead force the user to have their device full-disk encrypted. You can use DevicePolicyManager to see if the device has full-disk encryption enabled, and you can refuse to run if they do not. Then, the data is encrypted, as is the rest of their device, but you are no longer having to deal with passphrases and recovery scenarios — that's up to Google and device manufacturers.
Isn't there any other way to decrypt the data?
Only if you have a vulnerability in your app (a.k.a., a backdoor). This is the ticket-stub-and-chewing-gum scenario. The point behind encrypting data is to make it so that it cannot be encrypted without the passphrase or equivalent security key.
So, another approach to your app is to dump all your key stuff and use KeyStore. Particularly on devices with a hardware-backed KeyStore, there's no way to really get at the key, short of unlocking the device. Here, you don't have to worry about the full-disk encryption (as you're encrypting the data) and you also don't have to worry about the user forgetting the key (because the user never has the key). It also saves you having to have the user enter a passphrase. But now you can't readily back up the data (as it's useless without the key), and if the user's device is run over by a bakery truck or otherwise destroyed, the data is gone. You could provide options for the user to back up their key (e.g., to removable media), but now you are reliant upon them remembering where they stored the backup, storing the backup key securely, etc.
Or make the same SecretKey as before?
Since nobody but you knows how you are creating this, nobody but you can answer your question.
I would also suggest that you read this paper, as it outlines how 88% of Android apps that they surveyed, who tried to cobble together their own crypto approach, screwed it up.

Android Keystore - can a user key be retrieved by root if he setuid to that user?

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.

Categories

Resources