In using Certification pinning development is saying that no 3rd party will be trusted with the https certificate, instead it will be stored on the device. If i reverse engineer an android apk, would i not have access to this certificate ? I realize its public but i could use it to do man in the middle attacks, correct ? Where should i put the certificate so that no one can access it ? I have *.cer certificate file located in resources folder in android but need to know how secure it will be there.
The certificate is not secret, so don't worry about someone reverse engineering your certificate. To pin the certificate, simply embed your server's cert into your app. Then at runtime, when the server sends you it's cert, compare it to the one you embedded to ensure they are the same. Do this in addition to all the usually SSL/TLS verification.
Related
My app needs to consume webservice, and I would like to authenticate app against server with certificate.
However, embedding keystore with signed key into package is considered bad practice (and explicitly warned against: https://developer.android.com/google/play/asi) as it can be extracted an decrypted.
I can generate private key with android provided keystore, and use it - but I still need it to be signed in order to verify it on server side.
In ideal case there shall be certificate chain, with trusted root authority and containing metadata of signed app package I could verify on server side.
Or is it somehow possible to use package signature in certificate generation process to prove that self signed certificate originated form untampered package?
A bad actor ("Trudy") can flash any custom Android ROM, including a ROM that removes package certificate validation during APK installation. Thus, any query that your app makes to its Android host OS is essentially a request to Trudy.
So, it might be possible to uncover the installation of a hacked APK with an unadulterated OS. But with an adulterated OS, all bets are off.
I think any solution for the client to self-validate would necessitate an authoritative validation of the host OS. Not easy.
Is it somehow possible to use package signature in certificate
generation process to prove that self signed certificate originated
form untampered package?
(1) Do you mean that each client generates a different self-signed certificate after installation and somehow cross-references this against the apk package signature in order to authenticate? Then no, this will not stop Trudy. (And it would not be useful in authentication, either.)
(2) Do you mean that the client has a universal private key embedded in the APK and that metadata on the package certificate can be used to verify against the private key? I do not know offhand if there are any available fields in the package certificate metadata in which to add this information. This is an interesting approach that you suggest. However, since Trudy might be the OS, theoretically Trudy could mock any result it wishes. I do not see this stopping Trudy.
This (SO) post by a developer for Proguard offers 5 options for handling secrets in your Android app. He notes:
Intrinsically, nothing on the client-side is unbreakable, but you can
certainly raise the bar.
I understand that you want user authentication of Webservice (API) using user's private key, and signed token would be verified at the server with user's certificate or public key already registered there at the time of user registration.
Are you looking to use external USB Token to store private key securely or you want to store the private key to be stored in Android device memory?
We have worked on such requirements on desktop (sample at https://web.signer.digital/Home) but not on Android. I know we can connect USB Cryptographic Token (like ePass2003 or others) to Android device with OTG USB and drivers for Android for some devices are available to access from Android but didn't worked on it actually. But this can be direction for you to look into.
A mobile application is public app, because an end user could possibly view and modify the app code. So, your application can't keep secrets from malicious users. That includes client certificates, which are required for mutual TLS (mTLS).
It is not safe to store any client certificate on the Android device for machine to machine (don't mix machine to machine with user to machine) mTLS authentication. It can be exported and then used on other devices by any user.
Operation systems (Android as well, some browsers, e.g. Firefox may have own) provides certificate storage, where CA certificates are stored and where client certificates can be stored.
It is a good idea to store user (issued for the user, not for the app/machine) client certificates there. Then mobile app should get an option to select which user client certs should be used for mTLS. But I want to authenticate my application without any user interaction. won't be possible. There must be at least initial user interaction: user client cert import to client storage, mTLS app configuration. That's IMHO the best and secure mTLS implementation. Real world example: Rocket Chat app.
You are asking for reverse TLS based verification ? Usually, clients verify web services because client's host OS trusts a particular CA certificate that is also used to generate the web-service TLS certificates.
The difference is:
web servers are protected and controlled by authors. Client devices are not. So, having a private key in app to sign the data sent to server is futile.
Still, You can explore Google's Licensing implementation with server side verification to enforce that a legitimately installed and licensed app can contact the server.
Developing a simple android application that will cast a URL (webpage) on bigger display.
For publishing "the receiver app must be served over SSL (HTTPS)". For that I have generated self-signed SSL Certificate and plan to use the same.
URL for publish
However, On trying to access the page from browser, it gives following warning:
The site's security certificate is not trusted! You attempted to reach
basilapps.com, but the server presented a certificate issued by an
entity that is not trusted by your computer's operating system. This
may mean that the server has generated its own security credentials,
which Chrome cannot rely on for identity information, or an attacker
may be trying to intercept your communications.
So my query is:
(A) Will self-signed certificate will work fine during publishing?
(B) If not, then do I need to purchase SSL certificate from trusted authority?
(C) Are there freely available trusted certificates services available?
Thanks
Self-signed certs do not work and yes, you need to get/use a trusted one form a known authority. If you can use App Engine, that works since it already has that. For development, either use http or use App Engine or even Google Drive (the last two support https).
i need to implement security measure for my android app which currently runs with http
I was reading on the ssl and found that we need root and intermediate certificates,
if i am not purchasing the certificate from outside how can i get the root and intermediate certificates ..
thanks
Do you mean you will be using a self signed or self issued certificate on the public facing server? (Neither of which I would recommend)
If you really want to try and do that then:
a self signed certificate sign's itself (it is its own CA)
a self issued certificate on windows for example use the mmc certificates tool, you can download the public part of any certificates in the trust chain (but then you'd need to get them on to a device for them to be useful and something owners of the devices would not like since I would bet you do not have proper key management in place).
A potentially better way would be to use a properly issued certificate for your production site which would allow you to validate the hostname and trust chain correctly.
But for your local dev builds have it ignore these two checks (I would also have it put up a Toast if it was running in this mode so you don't issue this by mistake).
I have a mobile app which accesses web services at https://myserver.com/mywebservice.
If I create a self signed certificate and I put it on my server, when the mobile app accesses the web service it sees the certificate but it doesn't recognize it as it is self signed. But in this case if I have a "man in the middle" attack, the attacker can create it's own certificate, so the app sees the certificate and again it doesn't recognize it.
Question: When you use a certificate like those from goDaddy, is iOS or Android programmed to trust goDaddy certificates in order to work, so the fake certificate that the attacker uses is considered invalid? So if I make the app trust my certificate, I can use my self signed certificate the same way?
Also How can I know which certificates are trusted by iOS or Android?
Generally your app or the OS needs to trust the CA that issued the server certificate for this to work. If it is issued by a CA whose certificate is pre-installed, things just work. If not, you need to either install the CA in the OS trust store or modify your app to to trust it. It doesn't really matter who created the certificate, VeriSign or goDaddy certs are no more 'special' than your self-signed ones.
As for getting a list of trusted certs, Android 4.x and later lists those in Settings->Security->Trusted Credentials. For earlier version you have to write some code to enumerate them. Don't know about iOS.
I want to perform extra validation for SSL connections I make in an android app.
Basically I need to be able to:
See if the certificate of the remote host I am connected to has Extended Validation (EV) status
Find out the root certificate authority for the certificate of the remote end. E.g. I want to know if it is a VeriSign certificate or not.
To elaborate a bit more, I am writing a client that needs a high level of security and our organization is using EV certificates from VeriSign on all servers. I want to prevent any compromised certificate authority, or anyone that can fool a certificate authority to forge a certificate for our domain be able to hijack the application.
Is this doable and if so, how? Is there a way to get more information about the certificate of the remote end from a URLConnection object or a HTTPClient object and so on?
First: you can't possibly 'prevent any compromised certificate authority' from issuing a certificate for your domain. If it is compromised, they can issue whatever they want. What you can do is create a trust store with a limited number of trusted CA certificates, say, VeriSign only. That way, even if an related CA is compromised and issues a cert for your domain, it wouldn't matter since you don't trust it in the first place. That would also take care of second bullet. To have additional checks you need to implement and install your own X509TrustManager. Check the JSSE reference guide for details.