Working with certificates in Java

This post contains a mix of java and certificate info. Note that you should definitely use the p12 format in Java. Using other types, like p8, usually end up causing issues in the end. One easy way is by creating a custom trust manager

The easiest way of doing this is: (See this link for a code example on stackoverflow

  1. Create a custom trust manager with your special certs
  2. Create a trust manager with the default certs
  3. Create a custom trust manager, which takes the custom and the default trust manager and try them both

Another way of doing it would be adding the certificate manually to the cacerts file. Note that you will either need the full certificate chain for it to work, or just the root cert might also work. Note that certs added to the java key store must be in DER-format. See below for converting between formats. When adding with the keytool, you will either need to specify the path manually, or add it with the -cacerts flag to add it to the main key store. The keystore will ask you for password, but the password usually is changeit

Adding to keystore

# Replace FILEPATH with the cert-file and ALIAS with any given alias, which can be anything, but must be unique.
sudo keytool -keystore /etc/ssl/certs/java/cacerts -import -file FILEPATH -alias ALIAS
# Example of adding through a noninteractive script. Note that -cacerts is used instead of -keystore ...
keytool -noprompt -trustcacerts -storepass changeit -import -alias myserver -cacerts -file /tmp/server.der

Show contents of keystore

keytool -v -list -keystore path-to-keystore

OpenSSL generation commands

Generate self-signed root ca cert

openssl req -x509 -sha256 -days 1825 -newkey rsa:2048 -keyout rootca.key -out rootca.crt

OpenSSL conversion commands

Unpack whole p12 into pem file

openssl pkcs12 -in infile.p12 -out outfile.pem -nodes

Unpack key from p12

openssl pkcs12 -in infile.p12 -out outfile.key -nodes -nocerts

Pack a p12 from pem and key

openssl pkcs12 -export -inkey certfile.key -in certfile.pem -out certfile.p12

Convert PEM/CRT to or from DER

Change -inform, -outform, -in and `-out- as appropriate

openssl x509 -outform der -in server.crt -out server.der

OpenSSL validation commands

Validate you have a key required by server

Validate that you can access an port protected by a key. You should get some verbose data but the connection should stay open.

openssl s_client -connect hostname:443 -cert outfile.pem -key outfile.key

Validate that you trust a server

This will verify your general settings. There will be a lot of text. Verify return code should be 0.

openssl s_client -connect ldaps-server:636 </dev/null

You can also add the –CAfile or –CApath flags for troubleshooting. To use –CApath you might need to run openssl rehash path/to/capath after adding the certs if you have a chain.

Verify a certificate locally without connecting

openssl verify -show_chain server.crt

Check end date of pem file

openssl x509 -enddate -noout -in outfile.pem

Download a certificate from a server

Add –verify 5 to get intermediary certs

openssl s_client -connect the.ldap.server.net:636 -showcerts < /dev/null > server.crt

Java8 - Cannot use higher ciphers

Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_DHE_DSS_WITH_AES_256_CBC_SHA256
Ignoring unavailable cipher suite: TLS_DHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
Ignoring unavailable cipher suite: TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384

Ignore due to america. You need to manually enable good ciphers if you have a low version of Java8. Otherwise you can also upgrade to 8u161 and it will automatically work.