Java Keytool How to Add Server Cert from Url/Port

Java keytool easy way to add server cert from url/port (for Windows)

Probably the easiest way is to use KeyStore Explorer. Just use the "Examine SSL" feature and then click on "Import":

Sample Image

Alternatively you can replace </dev/null | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' > ${HOST}.cert with manual steps. If you execute

openssl s_client -connect -connect www.google.com:443

it will output something like this:

depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = Google Internet Authority G3
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = www.google.com
verify return:1
---
Certificate chain
0 s:/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
i:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
1 s:/C=US/O=Google Trust Services/CN=Google Internet Authority G3
i:/OU=GlobalSign Root CA - R2/O=GlobalSign/CN=GlobalSign
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEgjCCA2qgAwIBAgIIZ20sUt50wGgwDQYJKoZIhvcNAQELBQAwVDELMAkGA1UE
BhMCVVMxHjAcBgNVBAoTFUdvb2dsZSBUcnVzdCBTZXJ2aWNlczElMCMGA1UEAxMc
...
htkxJVFaLUXScpkNQagWzehkj9BGdV4oztKMgTU8hcZEsiDKF0aZmaMfAXAF6u0r
0n9sKu3Ap0uSR0+G4PVDcJkJzw2UiUsu8IkkHy3HjKt4zCCrATjZ4FPgtFHSWv8d
ZmUdWJhgJ30s/EvOKn1uQ6QlPWaCJKc9W6JaJQTX6PjPDMs0sK90ss9vCIJ0dDw5
ud+EC4cT
-----END CERTIFICATE-----
subject=/C=US/ST=California/L=Mountain View/O=Google LLC/CN=www.google.com
issuer=/C=US/O=Google Trust Services/CN=Google Internet Authority G3
---
No client certificate CA names sent

Mark the lines starting with -----BEGIN CERTIFICATE----- up to -----END CERTIFICATE----- and copy them into a text editor. Save it as [host].crt. Then execute the keytool command.

If you want to automate these steps in a script, you'll have to install Cygwin or one of the suggestions in this answer here.

How to import an existing X.509 certificate and private key in Java keystore to use in SSL?

Believe or not, keytool does not provide such basic functionality like importing private key to keystore. You can try this workaround with merging PKSC12 file with private key to a keystore:

keytool -importkeystore \
-deststorepass storepassword \
-destkeypass keypassword \
-destkeystore my-keystore.jks \
-srckeystore cert-and-key.p12 \
-srcstoretype PKCS12 \
-srcstorepass p12password \
-alias 1

Or just use more user-friendly KeyMan from IBM for keystore handling instead of keytool.

Options for Programmatically Adding Certificates to Java KeyStore

Here's code you can use for clients to programatically add your CA at runtime. You don't need to put it in any store - just carry around the PEM encoded file. You can even hard code it into your program so there's no separate file to manage.

static String CA_FILE = "ca-cert.pem";
...

FileInputStream fis = new FileInputStream(CA_FILE);
X509Certificate ca = (X509Certificate) CertificateFactory.getInstance("X.509")
.generateCertificate(new BufferedInputStream(fis));

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(null, null);
ks.setCertificateEntry(Integer.toString(1), ca);

TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);

SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
...

You will need a trusted distribution channel to ensure your program is not modified while sitting on the server waiting to be picked or while traveling down the wire while being installed.


openssl s_client -host www.envmgr.com -port 443 -showcerts > cert_chain.crt

You should only need to trust the root certificate, and not the entire chain. The server is responsible for sending all intermediate certificates required to build the chain. If the server is not sending all intermediate certificates required to build the chain, then the server is misconfigured.

The problem you are experiencing is called the "Which Directory" problem. Its a well known problem in PKI. Essentially, it means a client does not know where to go to fetch a missing intermediate certificate. You solve it by having the server send all required intermediates along with the server's certifcate. See OWASP's TLS Cheatsheet and Rule - Always Provide All Needed Certificates.


Just bike shedding, but there's a whole nother can of worms here with Java (especially Java 7 and lower):

SSLContext ctx = SSLContext.getInstance("TLSv1");
ctx.init(null, tmf.getTrustManagers(), null);

You can improve upon it, if desired. See SSLSocketFactoryEx at Which Cipher Suites to enable for SSL Socket?. It closes some gaps in protocol versions, cipher suites, etc provided by default in Java SSLSocketFactory.

Java's keytool command with IP addresses

This snippet might work for you:

import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;

HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};

HttpsURLConnection.setDefaultHostnameVerifier(hv);

If you do try this code, and it doesn't work, please post what is printed for urlHostName and session.getPeerHost().

Also, why does having Windows and Linux boxes interoperating require the use of IP addresses rather than hostnames?

Certificate on the client's side?

Keystore

A Java KeyStore (JKS) is a repository of security certificates – either authorization certificates or public key certificates – used for instance in SSL encryption.

  • In IBM WebSphere Application Server and Oracle Weblogic Server, a file with extension jks serves as keystore.
  • The Java Development Kit maintains a CA keystore in folder jre/lib/security/cacerts.

Keystore comes in two flavors:

1. Trust:

A trust store contains certificates that are issued by somebody you trust, like a root certificate from a CA.

2. Identity:

  • An identity store contains your own certificates and they are used to authenticate you when you access an external service.
  • A trust store does not contain sensitive information, while identity stores contain very sensitive information like private keys.
  • Contains a demonstration private key for server. This keystore establishes an identity for the server.


I wonder if the client side should use a .cert certificate.

If you mean to connect to a HTTPS service, then you should export the server's SSL certificate and import in your server's keystore, probably you can import in jre/lib/security/cacerts.

Client is only required to have a SSL certificate if it is a 2 way SSL, meaning client is also required to send a SSL certificate to server because server has requested the same.

Why it is required because using SSL handshake server will send its SSL certificate and client will validate this certificate from its trusted list of certificates present in his keystore. If it is not validated then SSL handshake cannot be completed, and hence no communication can be established. So, you must have server's SSL certificate inside your trusted store of certificates.

I thought the client's certificate should match servers certificate,
but it seems that I was wrong.

Yes, you are right, SSL certificates of 2 different parties will be different.

Each party who requires a SSL certificate will generate the public-private key pair at their end and will raise a CSR request to a Certificate Authority (CA), who will generate the SSL certificate using the provided key.


How to export and import SSL certificates

To export certificate:

If it can be accessed using web then click on HTTPS icon, view certificate and follow export commands.

If it cannot be accessed using web then use openssl to export certificate.
Use below command

openssl s_client -connect host:port -key our_private_key.pem -showcerts -cert our_server-signed_cert.pem

To import certificate:

Use command - keytool -import -trustcacerts -file /path/to/ca/ca.pem -alias CA_ALIAS -keystore $JAVA_HOME/jre/lib/security/cacerts

Further reading on export and import:

  • Java keytool easy way to add server cert from url/port
  • http://www.grim.se/guide/jre-cert
  • https://www.sslshopper.com/article-most-common-java-keytool-keystore-commands.html
  • Using openssl to get the certificate from a server


Related Topics



Leave a reply



Submit