I'm writing a small Android app and I need to hide some variable values. I have a API key I got from the content provider who is providing me content to show in my app that I need to retrieve data from them. Because it is being used in an encryption algorithm, it is of vital importance the code isn't leaked.
I need to save the API key in my code and be sure it isn't retrievable by the bad people in the world. What I do now, is save them in my code as a variable:
private static final String API_KEY="mysupersecreatapikey";
After the app is compiled to an APK file, this is, in my opinion not retrievable anymore. Am I doing it in the right way now, or is there a better solution?
Thx in advance,
Daryl
You could store the API key in a file located in storage. You can encrypt the API key when you write it to the file and then you can decrypt it when you are reading it (upon program execution)
If you put the API key into the client in any form that can be used by the client it will be possible to get to it somehow. Maybe by unwrapping the APK and decompiling the code, maybe by traffic sniffing. That private static final variable for example can likely be extracted by a decompiler (if it's bytecode).
If you want to make really sure that none of your users can get to the API key then your app shouldn't be using it directly. Instead have it connect to a web service you set up that serves session IDs for example. That web service that runs on a server that you have control over (quite a few options) would then be the only piece of software that knows the API key.
But depending on the use case this might be a complete overkill solution to this problem.
Related
When you compile a .java file into a .class file, if you had a line like
String s = "This is a String"
If you open up the .class file in a text editor, you will see
This is a String
Somewhere in the file amidst the gobblety gook.
Which is fine and dandy for most stuff, but not when dealing with sensitive information like API keys.
Of course, one alternative is to read the API key in from another file, but that just makes it EASIER to find the key, as now the person can just open "key.txt" when they open the .jar file.
So how do you encrypt a string literal in your .class file?
When you send code to a 3rd party, you loose all control over it. Even if you where to embed the API key as an encrypted string, an attacker could still try, and potentially succeed in breaking it, which would make all your encryption/decryption efforts in vain.
The best solution, in my opinion, would be to not provide any sensitive information within the application, but rather provide it with an ID of some sort. Any sensitive values which it needs would be then pulled through the use of a secure connection.
If you use a key to access a 3rd party API there is no way to protect that key from the end-user IF you ship it with your code / application or you want your application to be able to access the 3rd party API without a middleman.
The end-user could just read all data send from your app to the end-point and know the API key. Regardless of any measures you took to encrypt it you will need to send it atleast once decrypted to the 3rd party.
The safe way to do this is to require your user to log in to a service provided by you, send a request to YOUR service and then YOUR service (which is presumably not located on the machine of your end-user) sends a request to the API with the key. So the end-user never knows of the key.
If you store the information in the class file, the decryption key should come from outside of the class. You can crypt the data, but if you have all the information within the class file, you are lost.
You should store API keys in config files. You have a different API keys for development and for the live, right?
Other possible solution is to use KeyStore, which allows you to store sensitive information in publicly accessible format. Only the holder of the secret key can decrypt the sensitive data.
Even if you keep that information encrypted in your class, a hacker can find the mechanism to decrypt that from your code only. So IMHO it's better to keep that encrypted information in some other file, and read that file. Also, restrict the access to that file using OS security mechanisms.
I recently found that the databases of Android apps are totally exposed. That said, my configuration is exposed, I save there passwords.
So, now my doubt resumes on java code.
String value = "example";
This could be an example where I store a password to pass by reference to webservice.
People, with some kind of software (like this example Is there a way to get the source code from an APK file?) could be able to get all the code? (I tried to follow the steps without success)
I read about http://developer.android.com/tools/help/proguard.html, how do I know that it's already implemented in my project?
When you create an Android project, a proguard.cfg file is
automatically generated in the root directory of the project.
I checked my root directory and I don't have that file.
Thank you guys.
Obfuscation does not guarantee that your code won't be de-compiled. people who get your apk will still be able to review the code (although the flow of the app will be significantly more difficult to understand). Function names, variables and class names are changed but the code is still viewable.
password and other sensitive information should be kept in Android's keychain , where it's protected. never save passwords in a configuration file (preferences file).
You can look into encrypting your local database with sqlcipher. Proguard obfuscates code but will not hide your passwords if you have them hardcoded anywhere, it is not a tool to be used for security[reference]. Also all of your network traffic is vulnerable unless you use some sort of TLS.
As you describe your app now it is trivial to get the passwords in your app.
You can use char[ ] instead of string data type for storing sensitive values like password. This will make it difficult to recover if someone takes memory dump as value is not present string literal pool if used char[] data type.
The app I am working on gets all the files from the sdcard but these files are really important and the app should maintain a security issue .So is there a way that the folder or directory that contains the file may be encrypted or locked with a key and only be used by my app?
Please help I am newbie and stuck at this point.
On Android, anything stored on the SD card is not protected by permissions and can be accessed by any application that has permission to touch the SD card (and by anything/anyone that can pull the card out and read it elsewhere). Basically, you need to assume that if you put resources there, they can be accessed by anyone. So, you are correct, you want to encrypt these resources so that even with that access, no one can access them.
Android includes plenty of support for well-known cryptography. In this case, you'll want to use symmetric encryption. The current best practice here is to use AES with 256-bit keys, all of which are natively supported in the Android class libraries. There are plenty of resources on how to do this in the developer documentation online and there is a complete rundown of all the issues you need to think about, and code examples of the entire process, in Application Security for the Android Platform (disclaimer: I'm the author of this book).
You do need a key to encrypt this data, and you need to keep that key secret (anyone that knows it can decrypt the data). You have two options...(1) ask the user for a password every time they use the application and then derive the key from that password, or (2) store the password in your application. (2) is dangerous as Android applications can be readily reverse engineered, where an attacker can simply look into your application and find the key. (1) is preferred as then there is no key stored for an attacker to recover...the tradeoff is that your users need to type in a password to use your application. What you should do here is a function of the risk analysis...how important is this data? Do you need it protected in a strong manner, or are you protecting it to just make things harder for an attacker? Only you can answer that, based on your use cases and the sensitivity/risk of your data.
Have a look at those resources:
http://source.android.com/tech/encryption/android_crypto_implementation.html
http://developer.android.com/reference/javax/crypto/package-summary.html
You should be aware that of course you shouldn't store the key to the encrypted data in cleartext but rather encrypt that itself with a password a user can choose or similar.
This is how to make a new folder:
String SaveFolder = "/Save";
String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
File mySaveFolder = new File(extStorageDirectory + SaveFolder);
mySaveFolder.mkdir();
Got this code in the public void onCreate
Now it makes a folder with the name "Save".
Edit:
I looked there is not a way to set a password or something.
Though I read here http://developer.android.com/guide/topics/data/data-storage.html#filesInternal it is possible to save files in the internal memory, where users can't get acces too, but I never used that, so I can't help you with that.
I was wondering what's the security of Android's resources folders (I'm especially concerned with strings). I know, I know, it would be ridiculous to store a password in Strings.xml. It's not like that, but how easy it is to snoop on these resources, to access sensible app info?
Unfortunately it is pretty easy to get to the resources. Tools like apktool enable to do that. I have raised a similar question here. You may want to take a look.
Easy on a rooted phone. Expect anyone can read your string resources shared preferences, etc. I just hooked up ADB, changed to /data/data/com.tumblr/shared_preferences and read my username and password in the clear.
You can also download and decompile the apk. If you need to keep it secret, encrypt it.
The primary rule of thumb here is that ANYTHING stored on the device is open for sniffing and cracking.
There is no such thing as local security against those in physical control of the device.
Even if you encrypt it, the keys for decryption have to exist on the device or be easily accessible by the device.
As a side note, this is the number one reason for features such as Remote Wipe.
So, if you plan on storing something sensitive or just plain don't want a slightly interested user to see the data you've stored on the phone, then you're out of luck.
I know that the xml files are scrambled in the apk, but there is a hacker tool for unscrambling them back to plain text. I can't remember the name of it but I found it OK via Google. It works unfortunately!
Okay I have a folder say... http://oldserver.net/file/index.jar
How would I be able to protect the file "index.jar" from being downloaded from regular web browsers?
I've seen this done before, I just want to protect it from being accessed from web browsers, and keep it strictly java download access only.
What I mean by java download access only is, I could simply use a java downloader to download index.jar. But I can't download it via web browser.
How would I protect the file "index.jar" ?
Thanks:)
You need to think about what this requirement means specifically - from the point of view of your server, how can it tell whether an incoming request is a "java download" or not?
In short, I don't think there's a way to do exactly what you're after. The classic way to secure resources would be by requiring authentication (i.e. you need a valid username and password to get the index.jar file) but it doesn't sound like that's what you want here.
Bear in mind that Java simply sends HTTP requests (or other protocols that it knows how to speak) down a connection. Any other program could send identical requests, so there's quite simply no way to enforce this limit in the way that you've specified.
One approach that might simulate what you're after is to not have the index.jar accessible via HTTP, so browsers wouldn't be able to get at it by default, and then access it via another protocol in Java (e.g. FTP, SFTP, whatever). Though as mentioned above, any tool that can speak this new protocol would be able to download the file.
Another approach would be to look for Java-specific headers, such as the User-Agent field (assuming this is populated with something recognisable). But again - this is not secure, as any tool could send through the same headers and impersonate a java download.
If you mean in your question that you only want your files to be downloaded by a specific Java application, then things get a bit more feasible. You can distribute an application that contains some authentication (e.g. public/private key pair) and have the server challenge for this when index.jar is requested. But even then this is dubious - by definition the Java app has to contain sufficient information to authenticate as itself; and by definition you have to distribute this information publically; so it wouldn't be difficult to extract the private keys and have some other application masquerade as your Java one.
Basically, I can't see any way around this issue given the confines you've stated. If there's a narrower scope you'd be willing to entertain you may be able to come up with a viable compromise, but right now the answer is simply "no".
Technically, you can't. Whatever request HTTP Java makes, another HTTP client program can be made that makes the same.
However, you can make it slightly more difficult. You can put the file behind HTTP digest authentication and include the password in the JAR of the Java program the password or can check the user agent server-side.
See e.g. get_browser() and Apache 2 authorization and authentication.
You can make your file read only so that no one can modify actual file but there comes a problem that even java cant modify the file.
So if you need to modify the file,you need to make a new file of same extension and copy entire data from main file to new file and delete the main file and modify the new file and change the name of new file to old file name.
There is a function in java to set read only:
File newTempFile=new File("mytext.txt");
newTempFile.setReadOnly();
You could create a web application that serves your file. Here you could check for the user agent string in the request and decide on that user agent string whether to serve the file or not. For this to work, your "java downloader" must have an identifiable user agent string and your application must "know" it.
Of course any bad guy who knows this, could make his browser send you the same user agent string, so this in not really secure :-/
If your index.jar is very important, do not make it available for download in any of the methods mentioned. As soon as it is available for download and ends up on the client computer, inside java or not, it will be hacked.
Some code should only run on the server.