Here's the situation:
I'm working on an application which allows automated management of network connections. Users are able to configure WiFi/VPN profiles through the application and the application will manage their connectivity to these profiles.
This was all fairly straight forward (well, the VPN side required some reflection hackery) except when I got to the point of managing these connections to networks which required certificate authentication. The trouble is that these networks by and large use self-signed certificates, and as far from what I've been running up against in android it seems to me that these certificates need to be accessible from the root cert store. I tried to create a private app keystore and install the certificates there, but as far as I can tell the WiFi and VPN segments of android can't get access to this.
Is there a way to install a chosen certificate in the application keystore, create profiles based upon this keystore, then send the completed profile to the android wifi/vpn manager to allow the preconfigured connection?
This seems like it should be possible, but I just haven't yet managed to be clever enough to get it to work.
Update:
When I try to create the wifi and vpn configurations I've attempted to reference installed certificates in the local application keystore. It's unable to find them once the configs are pushed to the OS, it seems. To my understanding once a certificate is installed it becomes part of a general keystore, either at the app or the os level.
I have to keep access to the certificates internal, so I can't push them to the SD card. Even if I were to push them to the SD card I wouldn't be able to require the user to manually install the certificate, I need this to be handled in the background to simplify the configuration. I've been digging through the source and haven't found any obvious solution to this, but I was just hoping someone had stumbled across this before and I was just missing it.
Thanks in advance for the help!
Update 2
For those of you still interested in how to do this, here are the packages/classes which you will need to take a look at.
com.android.certinstaller.*
android.security.Credentials
With a little bit of digging you can find the appropriate ways to construct intents to install the certs you need.
Also, as a side note, If the credential storage password has not been set on the device the initial intent you fire to install a certificate will instead only prompt the user to provide a credential storage password. The certificate will not be installed. There may be a way to work around this but I have yet to find it.
That's more than one question, consider splitting it. What exactly have you tried? VPN and WiFi don't use regular Java KeyStore's, the access keys and certificates via the keystore daemon. The actual keys and certificates are stored as files in /data/misc/keystore. AFAIK the API for this is not public, but you could probably launch the certificate installer intent, which scans the SD card for certificates and PFX files, and installs them (this is may not be public either). Settings->Location and security->'Install from SD card' does the same thing.
In short, I don't think you can do what you are trying to do using just the SDK APIs, you'll have to look at the source, and take the risk of your app breaking in the next Android version.
Update: the installer intents are now public in ICS, you can access them via the KeyChain class.
Related
I built a couple of test IoT hardware devices for home automation which I want to control with an Android app I also wrote.
The app will be used by several people.
My plan is to use Amazon IoT Core to let the apps send MQTT commands to the IoT devices.
Since my hardware devices are not very powerful (ESP8266 architecture) I'm going to authenticate via the Signature Version 4 (SigV4) scheme. This auth scheme is useful when the hardware device is not powerful enough to authenticate via the standard privatekey/certificate method; it requires a pair of key/secret IAM credentials to be hardcoded into the device firmware (instead of the certificate and private key).
I then created a test "thing" in the IoT Core console and I can successfully send commands from the apps to the devices (and receive data from the devices and show them on the apps).
My question is, do I need to create as many "things" as the IoT devices? Since each device will have its own IAM credentials, can I just use one shared "thing" for all the IoT devices?
I can't find any best practice online, not even on the official documentation.
The short answer is, don't go there.
A thing is a logical entity in AWS.
The reason to use many things is that you can:
Group them
Create a certificate for each one (with policies)
Use the shadow to manage the thing state
Search them
While you can do what you are saying, using IAM for things is not what AWS had in mind. IAM is supposed to be used by humans. You could use strong names and passwords, but you find it difficult to manage, and you hit the 5000 policies limit pretty quickly.
You can give all your device the same username and password, but then how would you revoke a single one when needed.
I'm not a hardware expert but if you really can't use certificates then you don't really need things but do have a look at AWS STS that will let you create temp credentials for your device.
You'll have to manage the login process somehow (not using AWS) and then generate an access key and secret key for each device.
I've been using Nikolay Elenkov's blog (http://nelenkov.blogspot.com/2012/05/storing-application-secrets-in-androids.html) to store encrypted password information in our android application. The requirements are such that we a) don't want to store the key/salt in our code directly, because this can be decompiled/removed, b) need to support back to android API level 14, and c) need to store password (encrypted) information on the device (i.e. can't currently use an OpenAuth token or similar system, as it would require server changes that can't be made right now).
So, on JB 4.2+ devices, I can utilize the newer secure credential storage, which doesn't cause any problems. For JB 4.1 and ICS devices, though, I need to use the aforementioned method of interacting with the keystore daemon through nelenkov's techniques.
The problem here is that when the secure credential storage is initialized, it requires that the user set up a device password/pin, as it uses this to base the encryption key used for the master storage off of. This is kind of a bad deal, because it is a big hindrance for the user.
Alternatively, I've looked at using a separate key store, based off of SpongyCastle. The problem with this direction, though, is that I would need to initialize it with some password (likely stored in my source code). This would mean that, if the device were stolen/rooted, it would be relatively easy to procure the contents of the "secure" key store, as the password could be retrieved from the app's decompiled source.
Is there a better solution to this problem that I'm not seeing, or is it just not possible with API versions < 18?
There are really only two ways to do this: either the user enters some kind of password and you derive your keys from it, or you generate a key and store it on the device. Using the device unlock password is a lot more user-friendly than having the user remember a dedicated password for your app only. BTW, on 4.2+ you still need a lockscreen password so nothing is changed compared to 4.0. As usual, if the device is rooted, the attacker can get the user's Google authentication tokens, and bruteforce the lockscreen password so you'd have much bigger problems. So think about your threat model first and decide how far you are willing to go. If the data is truly sensitive, use a dedicated password with sufficient complexity that needs to be entered every time the app is opened. You can also write a device administrator and require that the device is encrypted, that the lockscreen PIN/password is sufficiently long/complex, etc.
The alternative is to use tokens, either your own or from a third party identity provider (Google, FB, etc.).
I'm writing a ringtone gallery app which ringtones reside on a server and they can be downloaded by user.
What I want is to check and verify if the connection is really from my app not other apps or a HTTP request generator. for example I don't like someone write an app that uses my back end and show his ads in the app. It's like image leaching in web site which is prevented by checking the referrer.
It's not possible to insert a key in the app as android apps can be decompiled so easily. I thought of gaining the app signature and send it's hash as a key, but it's like any app can access other apps signature hash.
what about writing part of app which do the communication in native code? is it decompilable as easy as java code?
I really can't think of any other way and I don't like others use my resources for their benefit.
There are a couple of things you can do.
Create your own Certificate Authority, ship a certificate with your app and use two-way TLS authentication. This does not protect against decompilation and reverse-engineering but protects traffic en route.
Use the advice in this slide deck to detect modifications and debuggers.
Use Jelly Bean's hardware-backed secure storage.
At the end of the day, though, DRM is a lost battle. If the user has root access, all bets are off, with or without obfuscation (which native libraries are). The only question is how important is your data. For 90% of applications, running it through ProGuard makes it nearly impossible to untangle (especially if you use data flow obfuscation). Along with the certificate approach, that should suffice for most things.
Alternatively, try to change your model, so that you're authenticating the user and not the app - that's far simpler!
In Settings > Location & Security there is a section that allows the user to import certificates. There is also an option, "Use secure credentials" that "Allow[s] applications to access secure certificates and other credentials". I can find no mention of how to get to this in the documentation, and very few mentions of it online aside from people using it to connect to certificate-secured wifi networks. One of the only pertinent things I found was a post claiming that accessing these certificates was actually impossible for regular apps. Is this true? Does anyone know how to access these certificates if it isn't or documentation somewhere that states it is not possible?
Take a look at this Android Issue for some discussion on the topic:
http://code.google.com/p/android/issues/detail?id=11231
The Settings screen for installing root certificates can only be used for VPN and WiFi, unfortunately.
I'm writing an Android app that communicates via HTTPS with a server application. On the server side, I have to be absolutely sure about the Android app's integrity. This means that the server app needs to be sure that it's communicating with the Android app that I developed and not with a re-written one (e.g. after decompiling the original app or after having rooted the device).
Is there a possibility to ensure that? Maybe there is a possibility with the signature of the apk file?
Any hint is appreciated.
Regards,
Peter
You are trying to address a known problem:
You can never trust an application on an open device (mobile phone, desktop computer). In order to trust it, it should be tamper proof. An example of such device is a SmartCard. Mobile devices are certainly not it.
You should never send data to device that user is not supposed to see. The implication of this is that all business logic must be done on the server.
All requests to the server should be authenticated with user's credentials (username/password) and made via a secure protocol (HTTPS/SSL).
No way. Whatever is in user's hands, is not yours anymore. Even if you somehow manage to transfer the APK to the server for validation, nothing prevents the hacked program send an original copy to the server.
In order to validate that your software is running, the client devices need to be able to provide remote attestation services, which is one of many piles of acronyms in the TPM world. I found that someone has been working on providing TPM services, including IBM's IMA, which is almost good enough for what you want.
Details here: http://www.vogue-project.de/cms/upload/vogueSoftware/Manual.pdf (Google Quickview).
Of course, this is emulating the TPM, and requires patching the Android kernel. But perhaps one of the various manufacturers would be willing to build a model with the TPM hardware included for you?