开发者

Java and SSL certificates

开发者 https://www.devze.com 2023-03-31 01:54 出处:网络
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 to import the SSL ce

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 to import the SSL certificate that my website uses into my application... Something I don't know how to do.

If it helps, my SSL Certificate 开发者_开发问答is not self signed, rather provided by StartSSL AND I am using Eclipse IDE.

Could anybody point me in the right direction? i.e. What files do I need, where should I import them and what code do I need in Java, etc?


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:

  • You could instruct your end users to perform the activity of importing the StartSSL CA certificate into the Java truststore. Links that may help include this StartSSL forum thread (only the first 4 steps are needed to import the CA certs into a truststore), a GitHub project, and this blog post; a disclaimer - I haven't attempted using any of those and you ought to be using it at your own risk.
  • 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.


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"));


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


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


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.


That article contains the code for changing trust store's password and adding other certificates there:

thetechawesomeness.ideasmatter.info

0

精彩评论

暂无评论...
验证码 换一张
取 消