Creating a self-signed certificate for Apache and connecting to it from Java
May 02, 2019 [Java, Programming, Tech]Our mission: to create a self-signed certificate for an Apache web server that allows us to connect to it over HTTPS (SSL/TLS) from a Java program.
The tricky bit for me was generating a certificate that contains Subject Alternative Names for my server, which is needed to connect to it from Java.
We will use the openssl command.
Creating a self-signed certificate for Apache HTTPD
First create a config file cert.conf:
[ req ]
distinguished_name = subject
x509_extensions = x509_ext
prompt = no
[ subject ]
commonName = Example Company
[ x509_ext ]
subjectAltName = @alternate_names
[ alternate_names ]
DNS.1 = example.com
In the above, replace "example.com" with the name you will use for the host when you connect from Java. This is important, because Java requires the name in the certificate to match the name it is using to connect to the server. If you're connecting to it as localhost, just put "localhost". Note: do not include "https://" or any port or path after the hostname, so "example.com:8080/mypath" is wrong - it should be just "example.com".
The alternate_names section above gives the "Subject Alternative Names" for this certificate. You can add more as "DNS.2", "DNS.3", etc.
Next, generate the server key and self-signed certificate:
openssl genrsa 2048 > server.key chmod 400 server.key openssl req -new -x509 -config cert.conf -nodes -sha256 -days 365 -key server.key -out server.crt
Now you have two new files: server.key and server.crt. These are the files that will be used by Apache HTTPD, so put them somewhere useful (e.g. inside /usr/local/apache2/conf/) and refer to them in the Apache config file using keys "SSLCertificateKeyFile" and "SSLCertificateFile" respectively. For more info see the SSL/TLS How-To.
Checking the certificate is being used
Start up your Apache and ensure you can connect to it over HTTPS using curl:
curl -v --insecure https://example.com:8080
Replace "https://example.com:8080" above with the full URL (this time, include "https://" and the port and path.
To examine the certificate that is being returned, run:
openssl s_client -showcerts -connect example.com:8080
Replace "example.com:8080" above with hostname and port (no "https:// this time!).
Connecting from Java
To be able to connect from Java, we need a Trust Store. We can create one in PKCS#12 format with:
openssl pkcs12 -export -passout pass:000000 -out trust.pkcs12 -inkey server.key -in server.crt
Note: Java 8 onwards is able to use .pkcs12 (PKCS#12) files for its trust store. The old .jks (Java Key Store) format can also be used, but is deprecated.
Now you have a file we can use as a trust store, follow my other article to connect from Java over HTTPS with a self-signed certificate.