Our Android application is interfacing with a server than employs a certificate chain, with certificates issued by Verisign. We were able to establish SSL sessions with this endpoint so far. This Verisign certificate is due to expire next month.
Questions:
1. Should Server site get a new certificate reissued from Verisign and everything would just work?
2. Can the original certificate expiration date be just extended rather than issue a new one?
What can be done to ensure a smooth transition?
You need to be issued a new certificate, but it needn't be issued by Verisign. Any trusted authority can sign the certificate.
The key store containing trusted issuers is here:
/system/etc/security/cacerts.bks
You cannot extend a certificate, but you shouldn't need to. As long as the server certificate is issued by a CA you trust (does not to be VeriSign), things should continue to work. You might want to replace the cert sooner rather than later though, because people might have clocks that are off by a few days.
Related
I am trying to implement certificate pinning on my app. As far as I understood there are 3 types of pinning available:
certificate pinning; The certificate should be "hardcoded" in the app and compared with the ones from the server. This is kind of bad because if a certificate needs to be rotated an update of the app is required.
public key pinning; From my research it seems this is deprecated
SubjectPublicKeyInfo(SPKI) pinning; this is a hash of the public key. The advantage with this approach is that if a certificates neeeds to be rotated the public key of the new certificate can remain the same for the new certificate, this way an update is not required.
Based on what I've said, it seems that the recommended way to do this is SPKI pinning.
My app can connect to multiple servers, based on the ip which the user types at login.
This is my idea of implementing but I am not sure it would work.
I would create an Intermediate Certificate signed by a CA. Then create my own public-private keys. Then each server that my app can connect would need to request from me to sign their certificate with my private key.
The hierarchy would be something of RootCertificate(self signed by CA), then my intermediate certificate(signed by CA) and then leafs certificates for every server that my app could connect signed by my private key.
On the app I would store the hash of the public key from my intermediate certificate. Upon first connection to a random server the app will get 3 certificates: the one for the server, my intermediate certificate and the Root Certificate. When checking the hashes will find a match with my public key.
What do you think? Could this be implemented? Did I understand something wrong? Is this approach prone to mitm attack?
Thanks!
My app can connect to multiple servers, based on the ip which the user types at login. This is my idea of implementing but I am not sure it would work.
I would create an Intermediate Certificate signed by a CA. Then create my own public-private keys. Then each server that my app can connect would need to request from me to sign their certificate with my private key. The hierarchy would be something of RootCertificate(self signed by CA), then my intermediate certificate(signed by CA) and then leafs certificates for every server that my app could connect signed by my private key.
On the app I would store the hash of the public key from my intermediate certificate. Upon first connection to a random server the app will get 3 certificates: the one for the server, my intermediate certificate and the Root Certificate. When checking the hashes will find a match with my public key.
I would simplify this approach and just pin against each backend server and the Mobile Certificate Pinning Generator tool can help you with extracting the pins for multiple domains/ips, while generating the proper pinning configurations to use in Android and iOS.
Let's imagine that your mobile app needs to communicate with example.com, httpbin.org and google.com.
Just configure the domains you want to pin against in the Config tab:
After you submit the form you will land in the Results tab, and then if you navigate to the Android tab:
and on the iOS tab:
Below each configuration you have instructions on how to add each configuration into your mobile project and even a link to a step by step tutorial on Github that uses the Pin Test App for Android and iOS.
The advantage of pinning against each backend certificate is that you can now have each one auto generating their certificates with LetsEncrypt that keeps the public key between renewals, thus without the need to change the pins in the mobile app, unless a compromise of the private keys occurs. You can replace LetsEncrypt it whatever allows you to rotate certificates while maintaining the same public key.
Let's say that I have an app that transmits some sensitive info to my server. I want to reduce the risk of a man-in-the-middle attack on my users, so I pin the keys used by my server in the Network Security Configuration file.
But, let's say a user of my app does not trust the CA that issued our certificate, and has removed it from the list of trusted CAs, or maybe an OS update removes the CA because it has been found to be behaving badly.
Ideally, in such a case I would like my app to refuse to connect to the server. I only want it to make the connection if the certificate presented by the server is signed with a key in the pinset AND comes from a CA that is trusted by the OS/user. Does pinning a key in the network security config file accomplish this? Or, are pinned keys trusted no matter what?
The HPKP instructs the browser to store the signature for your server certificate for the period of time you specify. Using HPKP does not replace the standard certificate validation.
In your scenario the pinned PK in the browser will be valid for the server certificate your server is presenting, but the actual certificate validation will fail since the CA is not trusted.
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.