Is the AndroidKeystore app specific or device specific? - java

I just want to ask that the AndroidKeystore API used for storing keypair is device specific or app specific. I want to ask if two app using the AndroidKeyStore to store their keypair, then the information for both app will go into same keystore or they will have different keystore containers.
Thanks.

The keystore is app specific. You are allowed to choose the same keystore if you publish two apps, or choose a different keystore. Each has different pros and cons. Some of this is explained in the [signing considerations section here].(https://developer.android.com/studio/publish/app-signing.html#considerations)
If you choose the same keystore for your app it makes various things possible, like code or data sharing through permissions. This is only possible for apps signed with the same key.
On the other hand, suppose in the future you want to sell your app to another company. This can happen to small app developers, where another large game or app development company wants to acquire their app (and they can make a lot of money). If you have signed all your apps with the same key it is very difficult, as the large company needs to be able to sign the app they acquired, so you have to give them your signing key. But this makes it possible for them to produce versions of all your apps, which is not good security practice.
If it was me I would:
choose a different signing key for each app
have my app signing done by Google Play signing, then there are no worries if you lose or compromise your key (or keystore password), or if an annoyed employee takes advantage of your trust to abuse your key.

Keystore API for storage is App specific.
Read this...
Use the KeyChain API when you want system-wide credentials. When an app requests the use of any credential through the KeyChain API, users get to choose, through a system-provided UI, which of the installed credentials an app can access. This allows several apps to use the same set of credentials with user consent.
Use the Android Keystore provider to let an individual app store its own credentials that only the app itself can access. This provides a way for apps to manage credentials that are usable only by itself while providing the same security benefits that the KeyChain API provides for system-wide credentials. This method requires no user interaction to select the credentials.
You can read this on the official site https://developer.android.com/training/articles/keystore#WhichShouldIUse

It is Application Specific not a device specific.
In terms of what you do with it for Android and probably what you're looking for since you mention signing apk's, it is your certificate. You are branding your application with your credentials. You can brand multiple applications with the same key, in fact, it is recommended that you use one certificate to brand multiple applications that you write. It easier to keep track of what applications belong to you.

It is app specific. But you can use same keystore for multiple apps.
Important!!!!!! Keep more copies of key file. If your app is pulished on play store and you missed the keyfile, you never able to provide updates for your app.
You need to build apk with same keystore if your app is already live on playstore otherwise google will not accept your build. You need start again from fresh upload with different package name. App with same package name is also not accepted. You will loose all your app’s rating and download figures as well.

Related

Is there a way to get alternative of signature key of my android app

Just like getting signature of app ( which unfortunately is accessible from any other app and not my app only ) is there any secret key for every app that can't be returned expect from my app so I can use for anti modding
I think you misunderstand what signing is for. Signing, on an open platform, does not prevent other people from modifying data. What signing does is authenticate that data is from a particular person. But if I take your apk and resign it with my own key, I'm not claiming that this is an #ArabWare app, I'm claiming its my app. It just so happens to have your code. Signing does not prevent this.
The only way to make signing prevent this is to have a closed system- to only allow certain people with certain signatures the ability to run software on it. Android is not a closed system. As such, signing cannot be used to prevent other people from resigning your app.

How to change the signing key of an app already published on play store? Is there another efficient alternative to contentProvider?

I had exactly the same issue like in that question: java.lang.SecurityException: Permission Denial: opening provider when implement content provider
I have solved it using: the answer of #CommonsWare
Where He says:
App B has identical <permission> elements as App A and both App A and App B are signed by the same signing key
But When generating the app bundles of my applications, I have forgotten to sign them with the same signing key
According to the research I have done:
It is not possible to change the singing key of an application once it is on play store.
My actual problem:
I have recently put two apps on play store which have the same <permission> element. When I install first the app A from play store, I will not be able to install the app B. When I first install the app B from play store, I will not be able to install the app A. One of my apps is not able to install when I install the other app first.
According to #commonware answer:
you would need to remove one of the two apps from the Play Store and
submit a replacement, with a new application ID, that is signed by the
same signing key as the other shipping app.
But I don't want to change the application ID of any of these two applications
Any idea about how to solve that issue?
Is there any other efficient alternative to ContentProvider to share data between two applications of the same author?
I have momentarily accepted the #Warlock answer but I am looking for a better answer.
It's possible to change singing key for app already in Play Store. But it has now major disadvantage which will be gone in few years. It will be working only on devices running Android 9 and above. So your mindSkdVersion has to be 28+. It's called key rotation and it's part of APK Signature Scheme v3. See this link.
Also I don't know other way how to 100% securely change data between two apps than trust same signing keys. Less secure way is only to depend on known applicationId (just sent Intent with "com.myapp.someaction") which attacker can of course use and sideload app or use other distribution. Bit harder way to break can be usage of Android IPC / AIDL directly.

Xamarin KeyStore PasswordProtection field

I'm utilising the JAVA KeyStore class to store my users OAUTH tokens for things like Dropbox.
It's working as it is, but I'm concerned about the security of it as I know very little about how, or where it is stored.
http://www.howtobuildsoftware.com/index.php/how-do/ZPR/c-android-xamarin-monodroid-sqlcipher-correct-way-to-store-encryption-key-for-sqlcipher-database
I am basing my code off of the sample above, one thing that is not provided is why the Password field is null.
So my question is, should this be null? Or should it contain a password that is unique to my application, if the latter, where would I protect my apps password, as I'm in a bit of a chicken and an egg scenario here.
Nick.
one thing that is not provided is why the Password field is null.
The issue in that implementation becomes what "password" should be used.
I'm in a bit of a chicken and an egg scenario here.
If a password was hardcoded within the application you might as well use null (IMHO... but I've worked with security researchers and have seen their toolkits and a hardcoded password supplied to a method call is less than 2 minutes of work for them to crack, so I would imagine a hacker can have it in even less time 😉), same as if the "password" was retrieved dynamically from a Web API over a non-secure channel.
Note: It is not that I am saying using a Null/blank password is OK, I am NOT, continue reading.
Prompting the user to input a password (in the form of a swipe pattern, passphrase, pin, etc..) before each keystore usage would make that implementation way "more secure", but at what cost of app|user usability, only you and your users can that determine that for the app's use-case. Personally I like it when my banking app prompts me for a pin and verifies that access via an SMS and another pin to entry, but that might just only be me. 😂
FYI: Being able to nick' your user's OAUTH tokens for multiple sites via just one app and password would be quite enticing for most hackers and researchers.
It's working as it is, but I'm concerned about the security
And you should be. 😜
That implementation you are referring to, IMHO, is very weak. At a minimum, it should be checking and using Android Keystone provider (AndroidKeyStore) if the app is running on at least API level 18. If your app only supports 18+ (or is running on a 18+ device), you should NOT be maintaining your own keystore file (again IMHO... but I can not imagine a security researcher disagreeing, but would love to hear their argument if they think you should).
Using the keystore provider removes you and your app from creating/maintaining/securing that keystore file as the OS does it and it uses the user's token/password/pin/lock-pattern/etc... to secure the actual filestore itself. No more chicken-egg problem.
Of course this does not cover your app checking for rooted device execution, malicious app installs, current security exploits tests, non-patched and/or missing security patches, etc... but at least it is a start 😎. (I've worked in some really secure devops environments).
Also that implementation is not checking for secure hardware; ie. KeyInfo.IsInsideSecurityHardware, KeyInfo.IsUserAuthenticationRequirementEnforcedBySecureHardware, etc....
Google has some good keystore training material that covers subjects like the keystore provider:
https://developer.android.com/training/articles/keystore#java

Using the Fingerprint Scanning hardware on Android devices to check multiple user's thumbprints against network connected database

I would like to use the built-in Fingerprint scanner on Android devices, or most Android devices, to scan the actual fingerprint image or data into my Android app, then send the fingerprint image or data to an API over the internet backed by a database of fingerprints, to see if a given fingerprint (given on any or most Android devices that have fingerprint scanners) matches someone in the database and returns their name (most basic description of my app that focuses on my main question).
Now, I know how to do the API part over the internet with many different programming languages, I'd probably use NodeJS or Elixir for that part, and I know how to do the algorithm to compare a given fingerprint against a database of fingerprints.
The problem I have is that by default and as per guidelines, the Android operating system and Android devices specifically prohibit accessing the internal fingerprint data, and only allow you to authenticate a single or a few users WITHIN a phone and NOT against an outside database with possibly thousands of users and fingerprints or more, and with the given fingerprint to be checked never having been used on a given Android device before, but simply stored in a database or uploaded from a different Android device to that database (served up as an API over the internet).
Also, getting an Android app to communicate with an API with a database backend is trivial. I don't want to address that either, and I don't want any answers to address that.
Specifically, I'm after a hackish way to get at the underlying fingerprint data/scan/image that the hardware produces, or some fingerprint data that is identifiable to an individual, to send to an API database backend over the internet, and let that backend compare the fingerprint data/scan/image sent to it with the database (and I know how to do the comparison part and all that). However, Google guidelines prohibit accessing the underlying fingerprint data in this way that I need for my App.
Solutions
One proposed solution is to issue every user of my app a USB hardware dongle that fingerprint scans, and use the custom API for this hardware. However, my app's use-case scenario involves random people with random Android phones (that already have built-in fingerprint scanning hardware), potentially thousands of people, and they will have little incentive to buy a USB hardware dongle that fingerprint scans, but if I could make it work, they would surely use my app with their built in Android phone fingerprint scanner.
Another proposed solution is to take an actual picture of a person's, for instance, thumb. I don't know if the resolution would be high enough or if this would be practical enough for fingerprint scanning. So my first actual question is (Question #1:) Can a picture taken with most Android phones, in outside conditions, with flash on, be used for fingerprint comparison purposes against a database of maybe 1,000 users? And return the name of the given random user's fingerprint, which is stored in the database, or return that the user was not found in the database based on their fingerprint, using a picture of their thumb? Even if the answer is yes, this is not the ideal solution.
Another proposed solution is to use a picture of a person's face against a database of around 1,000 users with pictures of their faces, instead of using a fingerprint scanner at all. (Question #2a) Would this be accurate (taking a picture of a persons face and doing facial recognition) for 99%+ of cases, in outdoor conditions with the flash turned on? (Question #2b) If so, can you suggest some open-source software for this purpose to be used on the backend, compatible with say NodeJS or Elixir? Or any other programming language too if necessary... and again, this is not the ideal solution.
The ideal solution, if it would work:
Using Code Introspection in Java to interrogate the Android Fingerprint API to determine its hidden objects, methods, functions, variables, etc, and then using Reflection in Java (google it if you don't know what this is) and hack/steal the underlying fingerprint data/image/scan from the phone, then send THAT to the API with the database backend. (Question #3a) This is my primary question and the one I'm most interested in getting a good answer to. Do you know if this is possible, despite the restrictions built into Androids. (Question#3b) If it isn't possible with all Androids, is it possible with some?
(Question #3c) How would I go about this with Code Introspection and Reflection in Java? Which API and parts of the API should I focus on? I'm aware this is hackish and I'm fine with that.
I am aware of the following
As per Nexus FAQs
Your fingerprint data is stored securely and never leaves your Pixel or Nexus phone. Your fingerprint data isn't shared with Google or any apps on your device. Apps are notified only whether your fingerprint was verified.
which explains very well that you can use fingerprints for verification purpose only. Its just an alternative to any app lock available in marketplace.
and also:
FingeprintManager only has these 3 features:
authenticate : for authenticating user
hasEnrolledFingerprints : Determine if there is at least one fingerprint enrolled.
isHardwareDetected : Determine if fingerprint hardware is present and functional.
you can check FingerPrintManager docs here :
https://developer.android.com/reference/android/hardware/fingerprint/FingerprintManager.html
And I'm also aware:
"and capture the fingerprint data itself" Not possible, since that data simply isn't available. Google's fingerprint HAL implementation guidelines states that "Raw fingerprint data or derivatives (e.g. templates) must never be accessible from outside the sensor driver or TEE".
However, I have read it suggested that:
you can use android.hardware.fingerprint.Fingerprint.class
/**
* Container for fingerprint metadata.
* #hide
*/
public final class Fingerprint implements Parcelable {
private CharSequence mName;
private int mGroupId;
private int mFingerId;
private long mDeviceId; // physical device this is associated with
...
}
to compare against with enrolled one together with FingerprintManager inner class but visibility of api is hidden and you need use Java Reflection
/**
* Container for callback data from {#link FingerprintManager#authenticate(CryptoObject,
* CancellationSignal, int, AuthenticationCallback, Handler)}.
*/
public static class AuthenticationResult {
private Fingerprint mFingerprint;
...
}
This is suggested as an answer on the post: Fingerprint authetication of multiple users
But further information is needed to verify that this actually works in practice on all Android devices or at least some, and could work in my use case with a database backend.
Summary
I can have the users that are in the database scanned in / fingerprints registered, the first time with any method, I just need to know how to use an standard Android phone without a custom 3rd party USB fingerprint scanning dongle to scan fingerprints and send them to this database (and I already know how to send them to the database and compare them, I just don't know exactly how to get them from the Android device so I want to try a hackish-method of Code Introspection and Reflection.)
It may help to review the Android Open Source Project documentation on the Fingerprint HAL. In the Implementation Details section you'll see that no biometric information is to leave the trusted environment.
As discussed in the comments, while the use case may be be admirable, the desire to get Personally Identifiable Information (PII) such as the actual fingerprint image or hash is adversarial to the design of Fingerprint system in Android.
It behoves Google and the Original Device Manufacturers (ODM) to release a patch to remove such leakage, as HTC and Samsung had to do in 2015 as documented in this Ars Technica article about Severe Weakness in Android Handsets Could Leak User Fingerprints.
Ergo any valid answer here would become useless in a relatively short time, reported to bug bounty programs and/or by security researchers.
As pointed out by #halfer, while the application's end use case is benign, the side effects via a reduction in security for users and developers dependent on Android Fingerprint authentication mechanism is not.
Hopefully there is some other path to achieve your goal consistent with Android's architecture.

How to verify POST data is sent from Android app with correct SHA1 signature?

Recently my game has been hacked and one user submitted an impossible score to the server. The score was submitted with a verified checksum, and correct data.
I'm convinced that the user must have reverse engineered my APK file to find the POST request.
Now I wonder what would be a good way to prevent this from happening again and I thought about verifying the SHA1 signature of the app. Maybe this way I can make sure that the app is signed by me, and is not a reverse engineered and changed version of the app.
Would this be possible? Or would there be a better solution to solve this?
I am using LibGDX by the way.
First of all, you really have to obfuscate your code. You can find more information about ProGuard and code obfuscation here.
Second of all, you can use GoogleAuthUtil available in Google Play Services, which is available for devices running Android 2.2 or higher.
GoogleAuthUtil does exactly what you need:
Your client server calls go to Google via a HTTPS request, Google checks whether or not the call is made by an app signed with your release certificate, and then it sends the request to your server.
You can find official tutorials about how to implement this here and official documentation here.
Cheers!
1) Use code obfuscation for ex. Proguard. This kind of tools available not only for Java.
But be careful with that - obfuscated code may work slowly or contain additional bugs.
2) Add App Licencing check (this will check app signature with Google Play):
Watch this video with attention:
https://www.youtube.com/watch?v=TnSNCXR9fbY
As I remember he mention technics used at runtime to verify your app not hacked or modified (zip check, etc).
3) Make sure your app/server use secure connection (SSL/TLS) only with MODERN cipher suites. This will mitigate downgrade attacks.
You can use this generator to build config with MODERN cipher suites for your server:
https://mozilla.github.io/server-side-tls/ssl-config-generator/
Also you can use certificate pining on client side - this will mitigate authority attack.
Do not use plain HTTP connection.
4) Use some kind of request signing (like Amazon AWS does)
You can get core idea from their docs.
http://docs.aws.amazon.com/general/latest/gr/sigv4_signing.html
Also this article should be helpful.
5) Prohibit usage of your app on ROOT'ed devices by adding run time check. Because of on rooted phone it's easier to hack or analyze your app.
6) You can decrease fraud by adding some ban system to your online game - if somebody hack your app and send wrong data to your server => add this user to ban list on server side (by IP or by user ID, etc). Probably add users to this list temporary (ex 24 hr, 7 days)
7) + if you are using Json/XML as data formats for network layer try to use binary format like Protocol Buffers. Binary serialization formats more efficient and hard to reverse engineer.
If you want to verify the signature of your app without the possibility that this is cracked too, you would have to upload the whole apk and make the check on a server. This is not a practicable solution.
The only secure android app is a pure terminal app, which means you'd have to do all computing on a server. Most of the time this won't be possible because of latency.
That's why we Android developers have to live with this: an app is not 100% secure.
But you can get close to it.
You might want to read Security with HTTPS and SSL guide for securing your communication.
Also you'll want to ensure your client is hard to crack: android app piracy prevention and Combating Android App Piracy: Xposed
In your case you'll also want to implement server-side request validation:
If you have a game with a server side, users probably have an account. If a user sends a clearly impossible score, automatically disregard the request and ban the user (and his ip). (But also have in mind that this should never happen to a valid request, otherwise users might get angry and stop playing.)
You can obfuscate your code better and use some very obfuscated secret to sign your requests. With that you can increase security.
But if all your game run in client it can't be completely secure. Because it doesn't matter what you use to sign, if you do it in client it means you have the secret or private key in client and then it can be hacked.
To make it more secure you need to involve some game logic in server and then control in that logic that the user isn't cheating.
Verifying the integrity of your app won't be enough, since the request can be easily faked outside the app or modified in memory on the fly, using a rooted android environment. Even more, you cannot totally avoid it.
This is a problem shared by all applications running in a machine out of your control (all client applications). You can't never trust the data coming from them.
As I can see it, you have several choices:
Obfuscate the code and make the app more difficult to be reverse-engineered. Notice that this do not solve the problem, but minimizes it.
Move processing to the server. The more game-play is controlled by the server, the less vulnerable you app would be to this malicious behavior.
Automatically detect impossible scores and close their accounts
Cheers,

Categories

Resources