I have a Spring Boot App that is a consumer of a cloud API. The API key for that API is externalized using an #Value annotation. Generally, we create a separate run.sh file that looks something like this:
java -DaccessToken=abc123 -jar my-app.jar
One of our customers, wanted us to encrypt the run.sh file, so the API key wouldn't be stored in plain text on the file system, which we did using this method.
Now, that same customer also wants us to automate their rotation of the API keys every 90 days. It's fairly simple to request a new API key within the APP and then delete the old API key, but is there a way to securely store the API key in such a way that the APP can be restarted if the host computer restarts, but the API key is not stored in plain text on the OS. I can't think of a way to do this without storing something unencrypted.
Thanks in advance for your help.
Related
I'm working on an Android app (minimum Android version is 5.0 - API Level 21) that stores data in a local database via RoomDatabase. However, the data needs to be encrypted for which I used SQL Cipher. My question is what is the safest way to store the key used for SQL Cipher. So far, I have two options and a major 'concern' for both of them:
Using the Android Keystore - however my biggest concern here is whether a user with root privileges can access the Keystore?
Using NDK to create a key - from what I've seen the file can easily be decompiled and the key can be extracted somewhat easily.
The app itself is simple so asking the user for a pin/password would not be a way to solve this. The same applies for getting a key from a server since the app doesn't require constant Internet access.
Using Firebase may be the answer because:
It does not need constant network access it will cache the data.
The saved key is not in your app, it is in the web or inside the cache of Firebase service.
It is simple to setup.
You can use one of these products to save your key at Firebase:
Cloud Firestore, Cloud Functions or Cloud Storage.
Or you may use Firebase Authentication instead of saving key.
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.
As we know that a java jar file can be easily reverse engineered to get the source code, how should I distribute my twitter app which has been made using twitter4j so that on decompiling the jar file, the user is not able to get the app key and secret?
You can use a obfuscator program like one of the below suggestions:
http://proguard.sourceforge.net
http://www.yworks.com/en/products_yguard_about.html
http://www.e-t.com/jshrink.html
http://home.comcast.net/~shvets/Programs/Tools/CafeBabe/
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.
I am not able to figure out how to upload bulk data to the Google's servers bypassing the 10mb upload limit and 30 sec session timeout. I want to design an application that takes my standard SQL data and pushes it to the Google's servers.
I might sound naive but your help is most valuable for my project.
There's not currently a native Java bulkloader, so what you need to do is use the Python one. The process goes like this:
First, you'll need to download the Python SDK and extract it. Then, create an empty directory, and in it create a file called app.yaml, containing the following:
application: yourappid
version: bulkload
runtime: python
api_version: 1
handlers:
- url: /remote_api
script: $PYTHON_LIB/google/appengine/ext/remote_api/handler.py
login: admin
Now, run "appcfg.py update yourdir" from the Python SDK, and enter your credentials when prompted. appcfg will upload a new version of your app, which will run side-by-side with your main version, and allow you to bulkload.
Now, to do the actual bulkloading, you need to use the Python Bulkloader. Follow the instructions here. You'll need to know a (very) little bit of Python, but it's mostly copy-and-paste. When you're done, you can run the bulkloader as described in the article, but add the "-s bulkload.latest.yourapp.appspot.com" argument to the command line, like this:
appcfg.py upload_data --config_file=album_loader.py --filename=album_data.csv --kind=Album -s bulkload.latest.yourapp.appspot.com <app-directory>
Finally, to load data directly from an SQL database instead of from a CSV file, follow the instructions in my blog post here.
I wanna do the same thing also. So, here's my naivest concept to achieve the goal.
Web Server Preparation
Create a servlet that will receive the uploaded data (e.g. for data type
XML, JSON)
(optional) store it as Blobstore
Parse the data using JAXB/JSoup and/or GSON
Dynamically interpret the data structure
Store it using Datastore/
Client Uploader Preparation
Using a local computer, create a Java/C++/PHP script that generates XML/JSON files and store it locally
Create a shell script (linux) or batch file (windows) to programatically upload the files using cURL.
Please drop a comment to this one if you have better idea guys.