Given that it is not possible to store a symmetric key using the Android KeyChain API, is the following a secure way to store a symmetric key:
Part One: Key Generation and Storage
Generate symmetric_key
Generate (private_key, public_key), store them in the KeyChain
Encrypt the symmetric_key using the public_key as follows: encrypted_symmetric_key = public_encrypt(symmetric_key)
Store encrypted_symmetric_key in local storage (SharedPreferences, SQLite, etc.)
Part Two: Using the symmetric_key
When the app wants to encrypt/decrypt something it:
Loads the private_key into memory from the KeyChain
Loads the encrypted_symmetric_key from disk
Obtains symmetric_key := private_decrypt(encrypted_symmetric_key)
encrypt(symmetric_key, some_message) or decrypt(symmetric_key, some_ciphertext)
Concerns:
Would a rooted user be able to obtain the (private_key, public_key) pair?
If the phone is not rooted, is the app that created the (private_key, public_key) pair the only user that can read the keypair?
According to the documentation (https://developer.android.com/reference/android/security/KeyChain.html):
The KeyChain class provides access to private keys and their corresponding certificate chains in credential storage.
Private key means that it's asymmetric (the private and public key are the two parts of an asymmetric key).
In your part 1 - you describe the preferred way to store a symmetric key on an Android device. Your part 2 is correct as well (at least to my knowledge).
As for your concerns - you are also correct. On a rooted device - the keys stored on the devices are vulnerable , and can be obtained by a person with access to that device. On a non rooted device - only the app will have access to the keys it creates.
In regard to rooting - you can use a root detection lib like RootShell (https://github.com/Stericson/RootShell) to detect if the device is rooted and then act accordingly (disable you app on that device or something similar) and you should also look into Google's SafetyNet (https://developer.android.com/training/safetynet/index.html) to detect if the device is tampered with (it detects rooting as well).
Related
I am developing a password manager application that stores your accounts and their passwords in a database and stores a password of the application in a shared preferences so that your accounts can not be reached by others
what is the best way to protect the data
suppose that I create a method to encrypt the data and create a method to decrypt it so that a normal user can read the data
if a device is rooted can the hacker move the application data to another device with the same application so that he can read the database even if is encrypted because the application in the another device has the decryption method
is there a back-door method so that the hacker remotely transfers the data to anther device and decrypts the data by the application itself
If the encryption method contains generating random encryption key and storing it within the password string as a next line (multi-Lines are not allowed in passwords) is this a safe way because the hacker hacks the totally password string which encludes the encryption key then decrypts it with the application
suppose that I create a separate encryption key....It should be stored somewhere permanently....But if the hacker can access it can he crack the encryption by the application itself? if yes can the encryption key stored somewhere where the user can not reach it
note: making the encryption key related to the IMEI of the device is not a solution because I intend to make the application sync data between devices so many devices may have access to the same account
If someone has root, they own everything. From a fundamental perspective, they could pretend to be the user, your application would decrypt the content for them, and then they'd have the results.
Having the sensitive content be encrypted using a master password as a base means that it would be safe to some types of attacks -- but if the attacker can have a piece of software watch for that password entry they can still steal it. It does protect against some parts though, since when the software is "cold" (i.e. the password isn't there or loaded) the protected data is safe (if the encryption is solid).
There's a external library which is very good to encrypt the Shared Pref dat that uses Facebook Conceal
Hawk
I am looking to understand Android keystore for the purpose of storing passwords on device. (https://developer.android.com/training/articles/keystore.html)
In this article it says "Use the Android Keystore provider to let an individual app store its own credentials that only the app itself can access." This is exactly what I want.
So I think the way this will work is like:
1) I will generate a RSA key
2) Store the PrivateKey in the KeyStore
3) Store the PublicKey in some SharePrefs
4) Encrypt Password using the PublicKey
5) Encrypt Password using the PrivateKey.
However I think I am misunderstanding something because this article does not show
1) How to save PrivateKey to KeyStore (I don't see any API showing how keystore added the key)
2) Does not show how to decrypt data with PrivateKey
Infant why is this article talking about "Use a PrivateKey in the KeyStore to create a signature over some data." What does it mean to create a Signature over some data ??? (I want to decrypt data with PrivateKey). And why does it want to verify "signature previously made by a PrivateKey".
So I am lost at this point ... this article started me of in the right place but then by the end I am confused what it is trying to achieve.
Can someone suggest if what I am trying to do makes any sense at all ?
Or should I just save public and private key in my own db ? (not much security there but its the best I can do with given requirement of storing password on device).
Many thanks
Rgds !!!!
I am quoting this line from Using internal storage section of http://developer.android.com/training/articles/security-tips.html
By default, files that you create on internal storage are accessible only to your app. This protection is implemented by Android and is sufficient for most applications.
Now about encryption:
Keystore API is dealing with encryption of the data. And keys are used for secure communication and not for storing password. Passwords are usually irreversible hashes or maps. And do not require decryption but needs only matching.
For example: To communication if you send data encrypted other party involved in communication needs to know what the data is so required decryption key. So if you have sent "Hello I am Crypted" receiver must know you sent "Hello I am Crypted" as message.
For password if you enter some passphrase or passkey it needs to be matched with the stored counterpart. Like if "pass123" is your password stored as "rdi#$$+!#/b" then when you enter a password when process by checking algorithm it should match the stored value and you are authenticated it is not required to generate "pass123".
So, for your application you can use some mechanism(that generates almost unique and irreversible hash) to generate unique key/hash when password is entered and then store it in your app data.
I have an application that communicates with a server.
When the user logins to the application an Authentication Token is crated on the server and stored in the SharedPreferences of the application and whenever the application requests data from a web service the authentication token is validated.
My question is, is it secure to store the authentication token in the SharedPreferences? I'm asking because a user with root privileges can access the preferences, extract the token and use it.
Is there anyway to have more security in that regard?
In short, yes, that's a perfectly reasonable thing to do.
The best you can do on top of that is obfuscation only. If you keep the token in memory, a root user can peek into that. If you encrypt it, you have to store the encryption key on the device also or you won't be able to use the token… and the key can be stolen just as easily as the token.
If someone has root on the device, all bets are off. Don't optimize for that case. If your app is super-duper high security, don't allow it to run on rooted devices, or implement a remote-wipe functionality where the user can report their device stolen and you can invalidate the token on the server.
Android 4.3 introduced the Android Keystore. That purportedly provides a secure store for cryptographic keys. This could be used to store a key that's used to decrypt an encrypted token stored with traditional methods. However, the referenced link gives no mention of how a rooted device impacts the security of this.
UPDATE 2018: Most modern Android devices have hardware-backed keystores, via a trusted execution environment (TEE) provided by the SoC. This makes it impossible (see below) for hacker to obtain the keystore master key that would otherwise be needed to decrypt the keys you've stored in the Android Keystore.
Well, "impossible" is a strong word. It's better said as "infeasible". Meaning, you'd need something like an electron microscope to scan the bits fused into the SoC providing the TEE. If you are the type of person whose data warrants this sort of attention, you probably have bigger problems.
There is an easier and quicker way to encrypt data now as there is an implementation of SharedPreferences that encrypts keys and values. You can use EncryptedSharedPreferences in Android JetPack Security.
Just add AndroidX Security into your build.gradle:
implementation 'androidx.security:security-crypto:1.0.0-rc01'
And you can use it like this:
String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);
SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
"secret_shared_prefs",
masterKeyAlias,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);
// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();
See more details: https://android-developers.googleblog.com/2020/02/data-encryption-on-android-with-jetpack.html
Official docs: https://developer.android.com/reference/androidx/security/crypto/EncryptedSharedPreferences
If there is concern that the token could be read from SharedPreferences, a good rule of thumb is to provide a certain level of obfuscation to the data being stored.
This response outlines a simple class to obfuscate SharedPreferences data:
What is the most appropriate way to store user settings in Android application
I'm tring to figure out how to share data in a secure way between an unknow number of applications, each application has a different certification.
In my opinion, content provider is the best way to do this.(?)
But my problem is how can i secure the data from malicious applications without encrypting the data.
I want to set up a URI for each application and prevent malicious applications from approaching.
How can i do this?
The most secure way to do this is with an RSA key pair. Your content provider would need a connection to a web service to stay up to date on acceptable key pairs. The content would then verify the signature provided by the querying application, proceed to provide data.
Any other method would be open to attacks. For example, checking against the package name of the querying application can be easily spoofed, by simply installing a debug or signed version of the malicious application with an approved package name.
You would have to "squeeze" the key pair into the existing ContentProvider calls. The simplest way to do this is to have the RSA key passed as part of the Uri. Preferably, always the first path segment, ie:
content://mysharedcontent/rsakey/somegroup/sometable
Arguable, have the RSA key as the last path segment is good design:
content://mysharedcontent/somegroup/sometable/rsakey
Ultimately, it's a style choice.
Upon receiving a request, you should check your secure store (a file encrypted with SHA-1) if the rsakey is legitimate. If not check against server, to verify and update your local store at the same time.
With this, applications will have a relatively concrete and secure way of authenticating with your ContentProvider.
Currently I am using:
Algorithm_mode_padding="RSA/ECB/PKCS1Padding"
Provider="BC"
I have heard that ECB can cause patterns in the output. What is the most secure Algorithm, mode and padding for Android at the moment? I will be using this for license files.
Also, what is the best keysize to use when creating a new public and private key?
ECB isn't advisable in general, but worrying this much about encryption schemes and key sizes is moot if you're using it (presumably) to decrypt files on your device.
If you're decrypting a licence file in your application in order to verify it, then you would need to have the private key embedded in your application. So no matter what key length it is, the user would be able to access it.
On the other hand, you could retrieve the private key from a server dynamically (or similar), but at that point you may as well just do the decryption/validation all online anyway.