You're probably facing one of the most logical yet most complicate things to do on a plaform like Java and therefore also Android. Turns out that there's not a one-and-direct way of achieving that since there are lots of kinds of certificates and there's not a method for making a HTTP call for all of them, because some of them might be signed by unknown CAs, others have intermediate bundles required in order for the cert be valid, etc.
Probably a way that will help you is storing the certificate into the user's keystore and this way you can make HTTPS requests because they'll already trust the destination SSL certificate. In this case, you'll be creating a new KeyStore
, import the certificate and then make the HTTPS request:
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
// Some of these exist in more than one package, be careful to include these
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
// This would reference to your KeyStore to store the certificate
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null); // This will make a new store
// In the next line, specify the file path
// You can also export the destination certificate (in your case, Paypal's)
// put it as a hardcoded `String` and work with it.
InputStream is = ...;
BufferedInputStream bis = new BufferedInputStream(is);
CertificateFactory cf = CertificateFactory.getInstance("X.509");
while (bis.available() > 0) {
Certificate cert = cf.generateCertificate(bis);
trustStore.setCertificateEntry("myAlias" + bis.available(), cert);
}
Afterwards, making the HTTP request to the SSL server should work.
---- EDIT ----
You don't need to generate a certificate for a site, as this site already has one. You have to import its already existing certificate. I'm showing you an example of how to do it, it's done under Firefox and in spanish, but I guess you'll deduce the key words in your language.
Go to the site whose certificate you want to export. In this example, I'm doing Paypal
's, but you might do it for any site. Also take in consideration that a site might have many certificates, that means that, for instance, https://www.paypal.com
has one and https://sandbox.paypal.com
has another totally different. You'll need to check this.
On the left side of the address bar, click on the Green text that says Paypal, Inc (US)
(that announces that the site has a SSL certificate).
You'll see a screen like this:
Click on the More information
button and you'll see something like this:
Click on the See certificate
(or similar) button, and now you'll see this screen:
Click on the Details
tab, in the list, select sites one by one (in this case, firstly VeriSign Class 3 Public Primary Certification Authority - g5
, then VeriSign Class 3 Extended Validation SSL CA
, and lastly www.paypal.com
), and afterwards, click on Export...
at the bottom of that screen. You'll be asked to export a PEM
certificate.
What you have just done is exporting the whole certificate chain, but now you have to put it all together. Simply open a text file and append the three certificates you just downloaded one after other in the order you downloaded and having special care to not include additional spaces.
That's the certificate you'll have to import in your code. In the snippet I included, there's a place you need to put a path to a file, it would be this. Since you probably want to include that code for all your clients, you might do 2 things:
Import the certificate as a part of your project. This would make that any client running your app will have that cert, this way you can use the code above without any moddification, but you'd need to be careful when Paypal would change that certificate (they usually expire after a time and need to be replaced by a new valid one - you can see the expiration time of a certificate in the properties of the certificate).
Export the certificate as described above, put it in a public place (for instance, a web server) and each time a user runs your app, download it and verify if the certificate in the keystore is the same that you just have read. If it doesn't exist, simply import it for the first time. If it exists and doesn't match, update it. Else, you don't need to do anything.