What is the most secure encryption mode for Android? - android

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.

Related

Best Practice: Which AES settings to use for Android KeyStore

Android KeyStore provides a whole list of available ciphers, which leads me to the following question: Which combination would be Best Practice to use in 2019? Every combination seems to have its own set of drawbacks and as someone who is not a security expert, it is realy difficult to decide which one to use.
Some background information:
I am working on a Kotlin-based Android app which connects to an API. The user must provide a pair of username:password to authenticate to the API, which will then return a hexadecimal bearer token for future authentication. The connection to the API is already TLS-encrypted, so no need for additional encryption here.
The problem is storing the informations securely. The username as well as the password and bearer token have to be stored securely. A common solution to this problem seems to be to encrypt the credentials and store them via the Preferences API. As the encryption only happens inside the app and no key-exchange is needed, symmetric-key encryption looks like the way to go.
TL; DR: Prefer AES/GCM/NoPadding. Do not ever use AES/ECB/*.
In your situation, you'll want to prefer authenticated symmetric encryption, and the only option that provides this in the list you link is AES/GCM/NoPadding.
The benefit for you here is that, not only is your data encrypted, it is also safe from tampering - if someone or something modifies the stored data, you'll get an exception when you attempt to decrypt it. The other listed modes do not have this property. This means that the stored ciphertext could be modified and you wouldn't know - it may or may not still decrypt (I say may or may not as it can throw an exception in other circumstances, like bad padding after modification).
The drawback (and it isn't much of one) is that you must ensure you never use the same key and nonce together. If you do - and an attacker can access or view two different sets of ciphertext - it becomes trivial for them to break and decrypt. The easiest way around this is to simply always generate a random nonce. You'll be able to encrypt 2^96 times before you run into any issues!
If you can't or don't want to use AES/GCM/NoPadding for whatever reason, select from AES/CTR/NoPadding or AES/CBC/PKCS7Padding. Both have their own drawbacks. You'll need to find a way to prevent tampering yourself (HMACs are usually used). I tend to prefer AES/CTR/NoPadding as it is very similar (at least to use) to AES/GCM/NoPadding.
Lastly, do not use anything ECB related. ECB BAD.

Symmetric vs. Asymmetric encryption for encrypting images on Android

I am trying to create an Android app that encrypts data on-the-fly and write it to storage. Already implemented the app with no encryption, checked 100+ examples/posts of encryption on stackoverflow but couldn't decide which method to use.
At first thought of of using AES and did some googling to find how secure it is. Entering 16 or 32 character (better security, i hope) passwords every time doesn't seems convenient. As an alternative Asymmetric encryption came to mind. Encrypt with one key and decrypt with the other, so that i can leave the key used for encryption in the memory and use the other key only when data needs to be decrypted (like offline on a PC, or on another app).
Files that will be encrypted will be mostly images,video, audio recordings, office documents.
Does second method leaves any vulnerabilities? Between AES and RSA which one is better if i need to balance for speed and security. Data isn't anything top-secret, just need to prevent falling to wrong hands. The device is not encrypted, running KitKat. How well does both method stands against some kind of attack ?
EDIT: Describing two methods.
Method 1: Use password based AES encryption, manually enter 16/32 character password upon application start, clear the password after sometime/certain triggers from the memory. Enter password again when required.
Method 2: Use private/public key based RSA encryption. Leave one key, the one used for encryption on the device. Use the other key during decryption, which is scarcely performed.
This question is somewhat difficult to answer since you haven't actually described any methods, you've just named two encryption algorithms. If implemented properly, both algorithms are more than secure for your needs.
It is important to remember that RSA can encrypt data no longer than its key length (minus some for padding), so in most cases RSA alone is not enough.
If you are simply encrypting information on a single device and want the user in control of when it is encrypted and decrypted, e.g. with a password, you can use PBKDF2 to derive a key of x length (e.g. for AES256, 32 bytes) with a password string as input.
Don't bother using RSA if you aren't going to take advantage of its asymmetric properties. In most cases (but not all) RSA is redundant if no server or additional party is involved.
You don't describe your problem much, but if it was me, I'd use AES.
When using AES, please keep the following in mind:
Never use ECB mode.
Never use plain ASCII bytes as a key. You should use PBKDF2 or similar to derive a key, normally 100,000 rounds is good.
Always use a secure RNG to create your IV (if your cipher mode uses one, some, like CTR, use a nonce instead, but the concept is pretty much the same).
Always remember that AES does not ensure integrity. Use a MAC to detect changes in the ciphertext before decrypting.

What is wrong with using one session key for an entire session in hybrid encryption?

I am making an Android application which involves two phones exchanging a lot of data over several minutes. I would like this communication to be encrypted and have been researching the various cryptographic options available. It seems like the most suited would be a hybrid algorithm, that uses asymmetric encryption (like RSA) to exchange a session key and a symmetric algo (like AES) to actually encrypt / decrypt the data.
From what I know of hybrid encryption, every packet sent between the two devices should use a new session key, which is embedded within the packet (encrypted with the other party's public key) to facilitate decryption at the other end.
To save CPU, I am considering using just one session key which is exchanged using RSA, and then encrypting / decrypting all data using this key, so that I can save on costly RSA operations. However, I understand that this is not recommended? Can someone please confirm this and tell me how I should proceed?
EDIT:
Thought I would add some more information here -
The communication protocol is completely custom and my own. Data is sent in unencrypted UDP packets, with a lot of metadata and an encrypted payload. So that rules out using regular SSL / TLS.
Also, for every session I generate new private and public keys, exchange the public keys and then use that to exchange a session key which is used in AES. I am using 2048-bit RSA and 256-bit AES. This, AFAIK, is more than enough and probably overkill for most communication. I will admit that my knowledge of cryptography isn't excellent, but I'm reading and learning as much as I can to make this as secure as possible.
Nothing 'wrong' with it, just a security tradeoff. The longer the keys, the longer the session can be. You're trying to keep the key long enough, or the session short enough, or a mixture, such that key compromise is infeasible in the time available. You also need to consider whether it's OK to leak the data for the entire session if a key gets cracked, or whether you need the extra security of a new key per message or whatever.
Why not use a l long live TLS/SSL session? This does pretty much exactly what you want, efficiently and doesn't require you to write tricky crypto code you will almost certainly get wrong.
In general, almost any crypto system I am aware of generates one symmetric key for the entire session and uses that for the duration. This is what TLS does and what SSH does. I believe this is what IPSEC does. There is no problem with this from a cryptographic point of view assuming you use a sane cipher like AES have sufficiently large IVs/Counters/Nonces such that they don't repeat.
The one worry about using this is that if your secret key leaks, you loose all the data in the session. However, if your secret key can leak, so too can your private key. At which point an attacker could decrypt previous session keys and get the data even if you followed the one key per packet mode.

Android - Storing sensitive data in the sqlite database

I need to store sensitive data in a sqlite database in an android app.
How can I be sure this data is very safe?
I know I can encrypt the data using a key, but where do I store that key? I don't want to ask the user to fill in a key either, I just want it to work on it's own.
Because I am afraid of reverse engineering I don't want to put an encryption key in the code either.
I found out about SQLCipher. It says it's a very secure way of encrypting the data in the database, but why is it that way? Don't I also need to keep a key to unlock that information? Or is this really a perfect way of making sure the data is safe?
And if it isn't, what is an (almost) fail-proof way of storing sensitive data in an sqlite database?
You said...
I don't want to ask the user to fill in a key either, I just want it
to work on it's own. Because I am afraid of reverse engineering I
don't want to put an encryption key in the code either.
Unfortunately, you need to do one of these things (well, probably). You can ask the user for a password and then derive a key from that using an algorithm designed for that purpose (that's known as Password Based Encryption - PBE - and Android includes some good PBE algorithms standard). You could store the key in your code or as a resource within your APK, but then someone would be able to reverse engineer it. You can do so and obfuscate your code, which will slow down the reverse engineering process, but you cannot make it impossible (your code will need to determine the key at some point so it's just a matter of an attacker figuring out how it is doing it).
Other approaches that have been tried here include forcing your client to connect back to a server to retrieve the key over the network...but then what happens if network connectivity is interrupted and what prevents the server from giving the key out to anyone, like an attacker? Well, then you could use mutually-authenticated SSL to ensure only your client is allowed to get it...but then you need to store the client-side SSL private key...which is exactly the same problem you have now. :)
So...the bottom line is that you need a key (or something equivalent) to encrypt/decrypt the data. You can store it and make it harder for someone to reverse engineer it. You can inconvenience the user and make them type in a password. But...you need that secret knowledge somehow.
Symmetric cryptography requires a key to encrypt and the same key to decrypt. There is no way around it.
Do not store the key in the code because it can be decompiled (Like you've said).
Ask the user for a password on the first use and use PBKDF2 to derive a cryptographically secure key to use in the encryption.
Either the user has to enter the password or you need to store it in the memory. What I'd do is, ask the user to specify a duration where the key will be cached in the memory to use for decryption.
And if the duration is expired, the user WILL have to enter the password again.
I didn't check SQLCipher thoroughly but it says it uses AES-256. AES is a symmetric cryptographic algorithm and it needs a key to encrypt and the same key to decrypt.
Is it possible to let apps auto gen a random password? May be gen from place,time or others information this will no need to ask user's pass.

How to preserve sensitive information in Client-Side-Binary?

I look forward to develop an Android / iPhone application, those will be using a private API (Non-Free) with embedded client-key.
Now, since it is possible to reverse-engineer application binaries and scrap out strings. I am worried of losing my client-key and there by exposing the private API to the attacker.
How to manage this ? Can you provide links to articles discussing such situations ?
Considering I have development access to the private API, what mechanism can I built in to that to preserve the privacy of the whole system.
It will always be possible to use the private API if you have access to your applications code (see this thread as well). You can make it harder, though. And you can restrict the use of the API with the following options
1) if it's not "your" API, don't put the key into the app but into a server you are running to serve as proxy for the foreign service (you probably still want another key for your server to go into the app then)
2) encrypt/scramble the key so it is not grabbed easily:
simple example for scrambling: put the key into a file; generate a random file of same length; xor the key file with the random file (and write it to disk again); whenever you need the key read both files and xor them again (any reversable operation instead of xor will do - more complex operation, spread over your code will make it harder for the reverse engineer)
encrypt your key using a passphrase spread over you app (on deployment android apps are obfuscated anyways, so finding it gets a bit harder)
3) if it's your service or you have a proxy set up, restrict the number of uses per client/IP or offer only parts of the service over your proxy
Note, option 1 may even be required if you have a contract which forbids to make your key public.

Categories

Resources