Password-based encryption for Android and iOS - android

I am working on an IM app that has a native Android and a native iOS implementation. One of the required features is being able to encrypt messages by entering an ordinary password string. These messages must then be decrypted by entering this password. I was also told to "use AES".
My plan, which I have tried with near-success, is to take the password string, salt it with some context info that I know will never change, and generate a fixed-length key using something like MD5. I know this isn't super secure.
To decrypt, I repeat above, and I get the same key. Then, I decrypt the data with that key, and get the original data back.
I got this to work on Android and iOS, but they cannot decrypt each other's data, which tells me there might be implementation differences that I can't see and that I can't change. The first 16 bytes of the AES128-encrypted data on both platforms are always the same, but after that, they are completely different. What can I check for?
To be ultra-clear, the user experience is to be identical to that of sharing a zip file with a password. The user enters the password, at any time, from any device, and BAM, they get the unencrypted data. Sharing keyfiles or any of that stuff is NOT part of this.

There is no need to use any salt (at least I don't see any reason for that)
AES is a standard - no matter what is implementation, results will be this same.
This same output for first 128 bits and different rest of data means that you are using different cipher modes AES is block cipher and you are probably using it with 128b block size on both platform, so first block is encrypted this same way and next ones are encrypted with different keys. Please read more about block cipher modes

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.

Where to store my keys to encrypt data on mobile?

I don't understand what the hacker can see and cannot see when he enters in a mobile app, for example android. He decompiles the .apk, then sees some .class files. If for example, I encrypt a key/value pair in a file, I still need to call this key from the code, and if the hacker can see the code, no matter if the key is encrypted, he will know which key I am calling?
My goal is to keep some encrypted string in my app, for example the twitter account Id of my app.
Some topics talk about " a private key to read, what was encrypted with a public key ", but if I use them, I still need to store them somewhere in my app...
Don't completely understand your requirement but the rule-of-thumb is always assume that client is not to be trusted.
You have to ensure that
All decryption should be done in your server (which you trust).
The client should never be able to access the decrypted data (unless you want it to). Hence whatever part of your code that needs to directly access the decrypted data should be in the server.
The client should have only the encrypted data (if it must store data).
The client should not be able to access the private key you used to encrypt the data.
If in your case your client must be able to access the critical data directly, then your only resort is to use obfuscation techniques (Basically hiding your data/code, to make it hard to find/understand). Of course all obfuscation techniques can be defeated eventually by a determined hacker. You have to decide how valuable your data is, what are the probabilities a hacker will try and access your data.
To take an extreme example : storing your twitter account and password using obfusucation is very bad. Storing a twitter-url- might not be so bad.
you can get your keys from server while launching app. and also dont manage in app purchase detail in sharedPrefrence or Sqlite. because in rooted device user can see that data file from root browser or sqlite editor application so user be able to change value.
A very determined person can crack it, but it's a major pain to crack encrypted strings and will stop most hackers. Especially if you obfuscate your code with something like ProGuard.
Answer to a similar question for details on how to encrypt

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.

Encrypting strings

I have an Android application and within it some strings which I send through htpps. Is it possible to encrypt those hardcoded strings (such as for example passwords) in Android application to be unreadable from the apk file?
Regards,
So if I understand your question correctly, you want to store encrypted strings within the Android apk file (in strings.xml for example). If this is the case, yes, you can absolutely store encrypted strings wherever you please.
The kicker is that in order to decrypt these strings, you'll need a key. Wherever you end up storing the key becomes the weak link in this chain. If your app is reverse engineered and someone gets a hold of the key, your strings are no longer encrypted.
So to answer your question, no, it's not possible to do what want.
Check out What is the most appropriate way to store user settings in Android application and a whole bunch of other question. Basically you can obfuscate and encrypt to some extend but you will never be completely safe on a rooted device and against network sniffing attacks. That said though that applies everywhere.. find your best compromise between level of effort to implement and crack and the data you are protecting.
I think you should explain what do you want to do with this strings.
If you want just send password to server and make some kind of authorization, you can use MD5 or some other hash function to hide thode values. Hashed password can be compared with hashed password at the server side.
If you want to send encrypted text and decrypt it at the receiver side then you have to use some encryption algorithm, e.g. DES (some kind of encrypting key will be needed).

Categories

Resources