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).
Related
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.
I have been creating an app in Android recently, which has a login page. It's fully offline, so online or network-based solutions would not help me. I think there are two approach for me to accomplish this task.
Saving password hash in the preferences XML file
Saving password hash in the SQLite database
However, in my opinion both of these ways could be insecure because an user could load my app's data directory in a DDMS and then take out my preferences or database file and subsequently try to manipulate it.
Now, my question is:
Is there any fully secure approach (preferably not using files) or way to encrypt preference or database file?
Thanks in advance
SOLUTION (idea from Marcin Orlowski)
A relatively secure solution would be hashing password along with another string, which is only known to my app (with assumption of no resereve engineering), with this conditions, the attack could not replace my hashed string with his own hashed string.
No, there's no bullet proof solution. What's in the app can be extracted with more or less efforts or your app can be hacked/etc. If you need to store password, do not store plain as plain text. Do sha1 or md5 hash of it first and store the hash, so even if one would get hands on your prefs/DB then he still does not know the password (but he can try to brute force it using i.e. rainbow tables etc). Depending on sensivity of data you protect with password, using hash may be sufficient (if you do not encrypt data itself, then it makes no sense to go further)
Save the password hash in the private ContentProvider. SharedPreferences XML and Database file can only be get from DDMS if user uses rooted phone.
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
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.
What would be the best most secure way to handle confidential text in an Android app?
The basic structure is (text/int) and some similar variations of it.
The app only shows a selection of the (readable text /readable int) at a time, so decryption will only be done for very few pairs at a time.
I need to make sure that extracting the complete (text/int) information is practically impossible - if possible :-)
Is there any standard library/scheme to handle this?
Many thanks
EDIT (after getting some very interesting responses to this question):
It seems that even when the data is encrypted one could easily take the de-compiled code from the app, combine this with a self-written extraction routine, and hereby get all the decrypted info to a file. Since the encryption key has to be provided to users of the app, everybody could potentially get to the data this way.
So in summary there is no real good solution?
You can save your text/int pair into the SharedPreference.
Because it's not secure, you can encryt the data before saving it into the SharedPreference in the same way as Google do in the Application Licensing package.
More details can be found in the Implementing an Obfuscator part.
The code source of the AESObfuscator can be found in the SDK in the market_licensing/library/src/com/android/vending/licensing folder.
I think in your application you can use a symmetric cryptography and you can store your key in the Keystore. This key should be protected with password. Every time, when you run your application, it will ask the user for the password. If the password is correct then the key is extracted from the Keystore and used to decrypt your data. In this case, there is no difference where you store your data (text/int pairs) because all data will be encrypted. For Android SDK look at the package java.security and to the class java.security.KeyStore
If you want to supply your application with the data that you don't want to be extracted then obfuscation is a possible solution if you write in Java. If you want this functionality to be written in C/C++ then use Android NDK.