I am trying to establish a connection with a PHP script of mine in Java using the secure socket layer (HTTPS), but I have found out that to ensure maximum security/validity
I have found out that to ensure maxium security/validity I have to import the SSL certificate that my website uses into my application
You are partially right when you make that statement. You do not need to import your SSL certificate. It is sufficient that the StartSSL CA certificate be imported.
Additionally, there is no such thing as importing a certificate into a Java application. SSL support in Java relies on the concept of keystores and truststores, and not on some certificate packaged within your application. If you are publishing your application to be downloaded and executed by end-users, there is no need for your to publish your certificate or for that matter your private key in your application. The private key, and the associated certificate would be stored in a keystore, that only you may access.
The end-users of your application would rely on the SSL support within the Java runtime, that would enable the application to establish SSL connections to sites, after the server-certificate is verified. The Java runtime ships with a default set of CA certificates in a truststore, and the only prerequisite for SSL connections to be successfully established is that the SSL certificate of the server be issued by one of the CAs in the truststore. The certificates of StartSSL are not present in the truststore of the Java runtime, atleast as of version 6, and therefore:
Or, you could initialize your application with your own truststore using the -Djavax.net.ssl.trustStore=<path_to_truststore> -Djavax.net.ssl.trustStorePassword=<truststore_password>
JVM startup flags, or execute the following code before initializing SSL connections:
System.setProperty("javax.net.ssl.trustStore","<path_to_truststore>");
System.setProperty("javax.net.ssl.trustStorePassword","<truststore_password>");
This is a viable approach only if your application is a Java SE application that does not happen to be an applet (or an application with similar restrictions on how the truststore is specified).
It would also help to read up the Java keytool documentation.
I have found out that to ensure maxium security/validity I have to import the SSL certificate
No you don't. You only need that step if your clients don't already trust the signer of the server certificate, which only arises if the server certificate is self-signed or signed e.g. by an internal CA.
Have a look at the following article: http://stilius.net/java/java_ssl.php It contains code example which may help in case if you are trying to access your script from code.
Note that you either should use system properties
javax.net.ssl.keyStore
javax.net.ssl.keyStorePassword
to pass the SSL certificate to JVM or import it into JRE keystore by using keytool tool
That article contains the code for changing trust store's password and adding other certificates there:
thetechawesomeness.ideasmatter.info
Apparently the mailgun engineers for some reason don't want to give us clear instructions on how to solve this. This is what I did
We run tomcat8 and connect via jersey web services to the mailgun API. I followed this users instructions and it worked fine. Hope this helps someone.
On 1/22, we updated our SSL certificates due to Symantec's PKI infrastructure set to become untrusted. Some older versions of Java do not have the "DigiCert Global Root G2" CA.
There are several options:
Import the "DigiCert Global Root G2" CA into your "cacerts" file. Upgrade your JRE to 8u91 (or higher), which includes this root. To import the "DigiCert Global Root G2" You can download the root from https://www.digicert.com/digicert-root-certificates.htm. Ensure you are downloading the correct root certificate.
Once the certificate is downloaded, you'll need to import it into with a command like the following:
keytool -import -trustcacerts -keystore /path/to/cacerts -storepass changeit -noprompt -alias digicert-global-root-g2 -file /path/to/digicert.crt You will need to set the path to your Java Keystore and the location of the root certificate you downloaded.
So 1. /path/to/digicert.crt is the file you just downloaded. 2. /path/to/cacerts - This is in your JRE path. I "find / -name cacerts -print" this will help you quickly find all the java cacerts on your filesystem. For me it was /usr/lib/jvm/java-7-openjdk-amd64/jre/lib/security/cacerts
The following method loads the default (cacerts) keystore, checks to see if a certificate is installed, and installs it if not. It eliminates the need to manually run the keystore
command on any servers.
It assumes that the default keystore password (changeit) is unchanged, update CACERTS_PASSWORD
if not. Note that the method saves the keystore after adding a certificate, so after being run once the certificate will permanently be in the store.
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
/**
* Add a certificate to the cacerts keystore if it's not already included
*/
public class SslUtil {
private static final String CACERTS_PATH = "/lib/security/cacerts";
// NOTE: DO NOT STORE PASSWORDS IN PLAIN TEXT CODE, LOAD AT RUNTIME FROM A SECURE CONFIG
// DEFAULT CACERTS PASSWORD IS PROVIDED HERE AS A QUICK, NOT-FOR-PRODUCTION WORKING EXAMPLE
// ALSO, CHANGE THE DEFAULT CACERTS PASSWORD, AS IT IMPLORES YOU TO!
private static final String CACERTS_PASSWORD = "changeit";
/**
* Add a certificate to the cacerts keystore if it's not already included
*
* @param alias The alias for the certificate, if added
* @param certInputStream The certificate input stream
* @throws KeyStoreException
* @throws NoSuchAlgorithmException
* @throws CertificateException
* @throws IOException
*/
public static void ensureSslCertIsInKeystore(String alias, InputStream certInputStream)
throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
//get default cacerts file
final File cacertsFile = new File(System.getProperty("java.home") + CACERTS_PATH);
if (!cacertsFile.exists()) {
throw new FileNotFoundException(cacertsFile.getAbsolutePath());
}
//load cacerts keystore
FileInputStream cacertsIs = new FileInputStream(cacertsFile);
final KeyStore cacerts = KeyStore.getInstance(KeyStore.getDefaultType());
cacerts.load(cacertsIs, CACERTS_PASSWORD.toCharArray());
cacertsIs.close();
//load certificate from input stream
final CertificateFactory cf = CertificateFactory.getInstance("X.509");
final Certificate cert = cf.generateCertificate(certInputStream);
certInputStream.close();
//check if cacerts contains the certificate
if (cacerts.getCertificateAlias(cert) == null) {
//cacerts doesn't contain the certificate, add it
cacerts.setCertificateEntry(alias, cert);
//write the updated cacerts keystore
FileOutputStream cacertsOs = new FileOutputStream(cacertsFile);
cacerts.store(cacertsOs, CACERTS_PASSWORD.toCharArray());
cacertsOs.close();
}
}
}
Use it like so:
SslUtil.ensureSslCertIsInKeystore("startssl", new FileInputStream("/path/to/cert.crt"));