Saving constant values securely - android

I am working on a Android application related to secure data communication. I am using a few constant values in my application, and am saving them in constant.java class. I don't want these values to be reverse engineered, but even though I am using ProGuard for Android, for experts it's easy to reverse the code. These constants are very secure. I can use properties file or any file in res folder but this approach is not at all secure.
Can anybody can tell me how to proceed? Is there any file format I can save my constants or prevent properties file from reverse engineered. Is there any option such as saving it in .py python file format and reading it from Android code?

It is fundamentally impossible to securely store secret constants on a device, since hackers can reverse engineer them through static and dynamic analysis. You can only make it a bit more difficult, by obfuscating the values:
Compute them with some algorithm, instead of storing them literally. Even a trivial algorithm may increase the time needed to extract the constants.
Distribute the components of the values throughout the code.
Use native code. It is generally more difficult to reverse engineer, at least if the code and its API are sufficiently large and complex.
Maybe look into whitebox cryptography, which tries to weave constant keys into the implementations of cryptographic algorithms, in such a way that the constant keys can't be extracted. This is still the realm of research and high-end commercial solutions.
You might get some ideas that you can apply yourself from my presentation and from Scott Alexander-Bown's presentation at Droidcon in London.
You can also use a commercial obfuscator like the extended version of ProGuard, DexGuard, to harden code for you, with techniques like string encryption and class encryption.
How effective the protection is depends on the time and effort that you can invest, on the value of your product, on the time and effort that hackers are willing to spend, on their expertise, etc.
Similar question: Best Practice for storing private API keys in Android
(I am the developer of ProGuard and DexGuard)

The answer is Dont do it!. Secret constants are never secret. You should always assume your opponent is smart enough to reconstruct what you've hidden behind your smokescreen.
And anyway, you don't need to do it. For secure communications, instead use a public key infrastructure. Heres roughly how this works.
Your server generates a private and public key, and then you include the public key with your apps installation. It doesn't matter if the attacker finds this. All it allows is for your app to securely send a message to the server, and ONLY the server can decrypt it because only they have the private key.
So first thing your app should do is generate private and public key. Use whatever secure storage locker your OS provides to keep the private key safe. Its not invulnerable, but it's a damn lot more secure than anything you'll come up with. And then send the public key to your server.
Now you can securely send messages to the server using the servers public key, and the server can securely send messages to you using your public key.
Don't try reinventing the wheel here. Security researchers with serious qualifications in hard math and comp sci spend lifetimes coming up with these systems, and if you blow your implentation you leave it open for hackers to break in and steal your stuff. Use a widely trusted off the shelf PKI encryption library like OpenSSL and keep abreast of whatever source of security alerts covers that library.

Related

Hardware backed keystorage in Android

When searching through sites/blogs and articles about secure key storage on Android, I've found that hardware key storage isn't explained consistent. In the sense that some say that the keys are stored at the Trusted Execution Environment (TEE), while others say only the master key derived from a hardware key (baked in the TEE) is used to encrypt the encryption keys and is thus stored in the normal world.
So in summary, secure hardware backed key storage:
Keys stored in the TEE?
Keys stored in the normal world but protected with a hardware derived key?
Which one is implemented in Android? Or are both possible and is the implementation dependent on the processor manufacturers?
The litaturate is quite inconsistent.
Thanks in advance,
Gilles Callebaut
Generally, these two solutions are both possible, and also it is the recommended solution for TEE OS. You can just read the ARM and Global Platform's TEE whitepaper in detail.

Android shared library integrity protection

Is there a way to somehow 'protect' a native shared library (.so) for the Android platform against binary changing?
E.g. someone could overwrite a JMP instruction with a NOP after reverse engineering the application, and distribute that library to rooted devices.
Is there anything someone can do?
What I'm looking for here is ideas about implementing a series of checks (e.g. encryption, checksumming etc).
Of course since the platform does not look like it offers support for this (correct me if I'm wrong) it would have to be all 'client-side'. Thus the whole thing is a bit futile, but at least will hinder reverse engineering some.
Yes there are things you can do, and they will make it very challenging for the Reverse Engineer, but I doubt you'd be able to do anything that would stop Chris Eagle.
The best way to protect from modification is to take a SHA-2 of the .so after you compile it, and rehash each time at runtime, matching it against the known value. This check will be enforced on the client side, so a skilled RE could just modify the binary to ignore the check. It does make it a bit harder though. If you put checks all throughout your code and use different checking techniques then it extends the amount of work the RE has to do. Do know however that Microsoft has poured millions of dollars into anti-RE techniques and there are still pirated copies of Office and Windows out there. You'll never stop them all. My personal philosophy (now that I've studied RE myself) is that it is ultimately too much of a pain to try and stop them. Just make a good app, make it cheap, and people will buy. The miscreants that steal your stuff wouldn't have bought it anyway.
If your app calls home you could also submit the hash to the server for verification. Of course and RE can still bypass this but it is one more thing to do.

Encrypting data in Android

I would like to encrypt data in my Android app. I have little experience in what the current state of encryption is, either for Android specifically or in general. I remember years ago that the US had laws that prevented software companies from exporting strong encryption technology. I'm not sure if any of that is applicable today considering that Android is open source code.
What I want to accomplish is to allow a user to encrypt data using only a password. I prefer to avoid using private/public keys because this probably requires having to enter in those two keys by the user. In my app, the user should be able to encrypt/decrypt data using a password. Their data will be sent from one mobile device to another and it should not be possible to decrypt their data on the receiving end without knowing the password. I do use SSL when sending the data but that isn't good enough because the data needs to remain encrypted on the server before it gets relayed to the receiving device. If a hacker had access to my server, they could potentially read the data. For this reason, I want to encrypt it on the sending device and only decrypt it on the receiving device.
A number of issues I need to resolve:
Is there an encryption API that will let me encrypt just using a password but if not, then I'll consider using private/public keys.
What are the current encryption algorithms that I can use and are they available internationally or does the US put some restriction on using them?
Would I be better off creating my own custom encryption algorithm and modify it from time to time to prevent hackers from easily breaking it? Or would you discourage this? If so, why? If I change algorithm regularly, I will need to include an algorithm ID in the data in order for the decryption code to recognize whether it can decrypt that current version of the algorithm.
I'm not looking for any "extremely hard to break" algorithm but something that should be adequate. The kind of data being stored are images, videos, audio and GPS data. It would be nice if the solution worked on Android 2.2 and above. I don't see why any algorithm shouldn't work on these versions since algorithms should be independent of an OS. Nevertheless, maybe Android does use a built-in algorithm for only certain versions?
Edit:
Code I am using now for some basic internal encryption in my app looks like this, but I have my doubts it's sufficient enough:
import java.security.SecureRandom;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(clear);
Originally, the above line was:
SecureRandom.getInstance("SHA1PRNG")
but Google changed this in 4.0 and this caused my code to break. Anything encrypted with my previous code could no longer be decrypted with the default API for 4.0. I personally found that a major issue with Google because they broke compatibility. What's to stop them from repeating this again in the future? My encryption/decryption cannot be dependent upon Google's choice of breaking compatibility.
I am also forced to use 128 bit encryption because apparently support for 192 and 256 bits is not necessarily available on all devices, persumably because of local government laws.
Is there an encryption API that will let me encrypt just using a
password but if not, then I'll consider using private/public keys.
I've written an open source Java library that encrypts data with a password, using 256-bit AES. You can this find this on GitHub: JNCryptor. This is compatible with the RNCryptor project for iOS.
This may work for you on Android, or at least you can see how the code works and adapt it as necessary. (If you don't find it works as you'd like, feel free to raise an issue and I will adjust the library).
What are the current encryption algorithms that I can use and are they
available internationally or does the US put some restriction on using
them?
There are a myriad of algorithms available, but you will be fine if you stick something very standard, such as AES.
As far as I know, the US still forbids exporting software that uses 256-bit AES key sizes. There may be other restrictions in other countries too. But I am not a lawyer.
Would I be better off creating my own custom encryption algorithm and
modify it from time to time to prevent hackers from easily breaking
it? Or would you discourage this?
Do not do this. Always use a well-known algorithm that has been subjected to extensive peer review. There should be no need to regularly change your choice of algorithm, unless it has been known to be compromised.

Data encryption on Android, AES-GCM or plain AES?

My team needs to develop a solution to encrypt binary data (stored as a byte[]) in the context of an Android application written in Java. The encrypted data will be transmitted and stored in various ways, during which data corruption cannot be ruled out. Eventually another Android application (again written in Java) will have to decrypt the data.
It has already been decided that the encryption algorithm has to be AES, with a key of 256 bits.
However I would like to make an informed decision about which AES implementation and/or "mode" we should use. I have read about something called GCM mode, and we have done some tests with it (using BouncyCastle/SpongyCastle), but it is not entirely clear to me what exactly AES-GCM is for and what it "buys" us in comparison to plain AES - and whether there are any trade-off's to be taken into account.
Here's a list of concerns/requirements/questions we have:
Padding: the data we need to encrypt will not always be a multiple of the 128 bits, so the AES implementation/mode should add padding, yet only when necessary.
I was under the impression that a plain AES implementation, such as provided by javax.crypto.Cipher, would not do that, but initial tests indicated that it does. So I'm guessing the padding requirement in itself is no reason to resort to something like GCM instead of "plain" AES. Is that correct?
Authentication: We need a foolproof way of detecting if data corruption has occurred. However, ideally we also want to detect when decryption is attempted with an incorrect key. Hence, we want to be able to differentiate between both of these cases. The reason I ended up considering GCM in the first place was due to this Stackoverflow question, where one of the responders seems to imply that making this distinction is possible using AES-GCM, although he does not provide a detailed explanation (let alone code).
Minimise overhead: We need to limit overhead on storage and transmission of the encrypted data. Therefore we wish to know whether, and to what extent, the choice for a specific AES implementation/mode influences the amount of overhead.
Encryption/decryption performance: Although it is not a primary concern we are wondering to what extent the choice of a specific AES implementation/mode influences encryption and decryption performance, both in terms of CPU time and memory footprint.
Thanks in advance for any advice, clarification and/or code examples.
EDIT: delnan helpfully pointed out there is no such thing as "plain AES". So to clarify, what I meant by that is using Java's built-in AES support.
Like so: Cipher localCipher = Cipher.getInstance("AES");
In 2012 the answer is to go for GCM, unless you have serious compatibility issues.
GCM is an Authenticated Encryption mode. It provides you with confidentiality (encryption), integrity, and authentication (MAC) in one go.
So far, the normal modes of operation have been ECB (which is the default for Java), CBC, CTR, OFB, and a few others. They all provided encryption only. Confidentiality by itself is seldom useful without integrity though; one had to combine such classic modes with integrity checks in an ad-hoc way. Since cryptography is hard to get right, often such combinations were insecure, slower than necessary or even both.
Authenticated Encryption modes have been (fairly recently) created by cryptographers to solve that problem. GCM is one of the most successful: it has been selected by NIST, it efficient, it is is patent free, and it can carry Additional Authenticated Data (that is, data which stays in the clear, but for which you can verify authenticity). For a description of other modes see this excellent article of Matthew Green.
Coming to your concerns:
Padding: by default, Java uses PKCS#7 padding. That works, but it is often vulnerable to padding oracle attacks which are best defeated with a MAC. GCM embeds already a MAC (called GMAC).
Authentication: AES-GCM only takes one AES key as input, not passwords. It will tell you if the AES key is wrong or the payload has been tampered with, but such conditions are treated as one. Instead, you should consider using an appropriate Key Derivation Algorithm like PBKDF2 or bcrypt to derive the AES key from the password. I don't think it is always possible to tell if the password is incorrect or if the payload has been modified, because the data necessary to verify the former can always be corrupted. You can encrypt a small known string (with ECB AES), send it along, and use it to verify if the password is correct.
Minimise overhead: At the end of the day, all modes leads to the same overhead (around 10-20 bytes) if you want authentication. Unless you are working with very small payloads, this point can be ignored.
Performance: GCM is pretty good in that it is an online mode (no need to buffer the whole payload, so less memory), it is parallelizable, and it requires one AES operation and one Galois multiplication per plaintext block. Classic modes like ECB are faster (one AES operation per block only), but - again - you must also factor in the integrity logic, which may end up being slower than GMAC.
Having said that, one must be aware that GCM security relies on a good random number generation for creation of the IV.

Android + JSON Securing against decompilation?

I want to be a able to securely send data from my Android App to my server using HTTPS and JSON.
With HTTPS i am secure against sniffing but not against decompilation so i will also use Proguard to Obfuscate.
My question is with JSON being a plain text method of sending data a skilled decompiler will be able to work out what is being sent and received. So what is a better way of sending this data - If i assume that at some point someone will decompile the APK or JAR (depending on how i launch the program).
I could obfuscate the JSON
"x":{"xx":12345678}
But again i think it will just be a matter of time before someone works out that i am trying to send a time code etc.
Well... you can't. Sorry. If you could figure this one out, the music and movie industry would make you a hero.
There is no way to prevent decompilation. Obfuscation makes the decompiled results harder to use but a dedicated black hat will still be able to use that.
The best combination I've found is the DojoToolkit and the Closure Compiler in Advanced Mode.
Closure in Advanced Mode makes JavaScript code almost impossible to reverse-engineer, even after passing through a beautifier. Once your JavaScript code is obfuscated beyond any recognition and any possibility to reverse-engineer, your HTML won't disclose much of your secrets.
This link for using the Dojo Toolkit with the Closure Compiler in Advanced Mode for mobile applications:
http://dojo-toolkit.33424.n3.nabble.com/file/n2636749/Using_the_Dojo_Toolkit_with_the_Closure_Compiler.pdf?by-user=t
If you use the Closure Compiler, you can then throw in an encryption engine writting in JavaScript, then encrypt your JSON data. With the level obfuscation provided by the Closure Compiler, it will be very difficult for people to reverse-engineer your code to discover the key you use to decrypt.

Categories

Resources