Is it possible to deliver a private key with an Android app, which is the same for all app installations, and which cannot be extracted from the .apk file?
The reason I need this is the following:
When my app sends data to the server, (let's say an app key, which may be public), it also sends the hash of this app key, signed with the private key installed during the installation process.
The server checks the signature by applying the public key to the signed, hashed app key and comparing the result to the hashed app key.
Only if the signature is correct, will sensitive data like an app secret for the access of my API be returned.
This way I like to make sure that only my app can use my API and the app secret cannot be stolen (app key and app secret are necessary to retrieve an access token from the API).
Google Instance ID seems to be what I am looking for (runs on Android and iOS). This library enables you to assign unique IDs to each installed app instance and to perform a check on the server side, whether the ID belongs to your app.
More information can be found here.
Related
It can be a one time thing, as the passed key can then be stored on the users device via android keystore.
What I'm ideally wanting, is a secure place to store a secret key, that is accessible by my app, which on installing the app, can retrieve and store this key locally.
My immediate thought is using certificates but I don't know too much about them, nor any service that can help me.
Any ideas?
I have an Android application that sends info to a server, but needs each user to have an assigned API key that they use. The apk build is, therefore, universal, but I need to attach a unique config file to the download containing the API key.
SharedPreferences (or SecurePreferences) is ok for writing and reading from the app on the device, but not for sending down a pre-configured file?
*.properties needs to be compiled with the app?
AndroidManifest.xml meta-data, this is just used at build time?
What's the best way to have the unique API Key downloaded, have it stored somewhere private to the app, and accessible to the app?
What's the best way to have the unique API Key downloaded, have it stored somewhere private to the app, and accessible to the app?
You should get API key specific to user/app on successful authentication or login, then after you can store retrieved key in your SharedPreference of the application.
Set SharedPreferences mode as private mode so other application can not read/write it.
I am developing an mobile (Android) API that connects to my server and fetch a few data and send it to the mobile (Android) app that use this API.
I want to be sure that, only persons who has been authenticated with my servers can use the API.
I can give them a user name or password to use the API but what if someone else use the user name and password and send same request to my server(Reply attack). How can I avoid this attack on my API?
I have seen that google use an API key on his APIs like direction that is associated with a digest of signing key; but I am not sure how it is working and whether something like that can help me or not?
Actually I want to be sure that the client APPLICATION that is requesting to the server is the same APPLICATION that I myself has been developed it (not a decompiled and recompiled version of my app).Does some one knows some standard way to authenticate the users of API?
so from what you explained i assume you want to ensure that only Applications you want should be able to use server APIs.
there is not any complete way to ensure this but some steps can make a great protection:
1- you must have a complete list of packagenames which are allowed to send you request
2- you must proguard your sdk code (the aar file you said) and take the username password of developers from out of this aar so there would be no need for developers to know about codes inside the aar something like below:
YourSdkMainClass theInstance = YourSdkMainClass.getInstance("username","password");
3- you must get the application packagename and send it along with username and password every time you call any API (making a encrypted string out of three would be great) - or you can choose a mechanism where you generate a hash token out of these three on a specific API that is called at the beginning of the application and use that token for calling other APIs after that (the token must be invalidated after some hours of not using and new token should be generating)
4- at the server side you must check the received packageName and compare it with the packageName (or list of packageNames) allowed for that specific developer. if everything is OK then response to API call (or send back the token)
NOTE: this scenario can be improved sending the signature of APK instead of packageName. using signature key, multiple apps with same packageName wont be able to send request to the server. of course you need to have signature of the APKs of your developers in server side (ask them when you want to give them the user password)
but all these are perfect if you proguard the aar in a good way.
What is the best place to store API keys, Database encryption keys etc. in the app code so that nobody can get it by decompiling the code ? I used proguard to obfuscate the code but it didn't work on Strings.
There is no way to store them in the app. The app can be decompiled or executed on a modified device which provides more access to the app's memory, or the app can be modified by the attacker to add additional logging of network or storage/database traffic, etc.
For authenticating to servers, your app should probably obtain auth tokens (or similar) by exchanging user-entered credentials for such auth tokens or by obtaining these auth tokens from AccountManager or similar APIs. You could also use SafetyNet Attest API (https://developer.android.com/training/safetynet/index.html) to attest to your servers that it is your app signed with your signing key which is making the request.
For database encryption, the app could generate a random encryption key on-device, either linked to user-entered credentials or stored in Android Keystore, or simply rely on protections offered by Android to apps. It depends on your threat model (i.e., why do you think you need to encrypt databases?)
I have been using AWS (Amazon Web services) and in particular simpleDB for a couple of smartphone apps using their iOS/android client libraries.
So far, the data was very benign so I didn't worry too much about data protection.
My next app project will require a "users" table/domain containing usernames and passwords.
What I'm worried about is that someone reverse-engineer the Android java version of the app, then it will be easy to get all the simpleDB data, including all the passwords.
the basic TVM thing (Token Vending Machine, where a temporary token replaces the AWS credentials which are not in the code) doesn't seem to protect against that scenario so it would be great to hear what people think is the recommended approach to do the login part of the app using AWS without being completely unsafe.
Having the passwords table stored somewhere else/accessed in a different way?
Any comment appreciated, Many Thanks.
I can suggest you two approaches to keep your app protected -
1st Approach :
You can keep your AWS secret key into a file with in your app that will be encrypted using private key. On start-up, your code will read that file using public key and can only get your AWS secret key. Please remember following points in this approach -
Your code must be obfuscated.
Your secret key must be in encrypted form into the file so you will get double protection.
Your file must be digitally signed.
2nd Approach :
You can also create your own web site that will manage your user authentications and if user is successfully authenticated it will send AWS Secret key after encrypted it with private key, in his response to the app and your app will use that AWS Secret key after decrypting it with public key. Please remember following points in this approach -
1. Your response must be returned in encrypted form.
2. You site must be secure and must run on HTTPS.
3. Your code must be obfuscated.