How to import a .cer certificate into a java keystore?

JavaCertificateKeystore

Java Problem Overview


During the development of a Java webservice client I ran into a problem. Authentication for the webservice is using a client certificate, a username and a password. The client certificate I received from the company behind the webservice is in .cer format. When I inspect the file using a text editor, it has the following contents:

-----BEGIN CERTIFICATE-----
[Some base64 encoded data]
-----END CERTIFICATE-----

I can import this file as a certificate in Internet Explorer (without having to enter a password!) and use it to authenticate with the webservice.

I was able to import this certificate into a keystore by first stripping the first and last line, converting to unix newlines and running a base64-decode. The resulting file can be imported into a keystore (using the keytool command). When I list the entries in the keystore, this entry is of the type trustedCertEntry. Because of this entry type (?) I cannot use this certificate to authenticate with the webservice. I'm beginning to think that the provided certificate is a public certificate which is being used for authentication...

A workaround I have found is to import the certificate in IE and export it as a .pfx file. This file can be loaded as a keystore and can be used to authenticate with the webservice. However I cannot expect my clients to perform these steps every time they receive a new certificate. So I would like to load the .cer file directly into Java. Any thoughts?

Additional info: the company behind the webservice told me that the certificate should be requested (using IE & the website) from the PC and user that would import the certificate later.

Java Solutions


Solution 1 - Java

  • If you want to authenticate you need the private key - there is no other option.

  • A certificate is a public key with extra properties (like company name, country,...) that is signed by some Certificate authority that guarantees that the attached properties are true.

  • .CER files are certificates and don't have the private key. The private key is provided with a .PFX keystore file normally. If you really authenticate is because you already had imported the private key.

  • You normally can import .CER certificates without any problems with

     keytool -importcert -file certificate.cer -keystore keystore.jks -alias "Alias" 
    

Solution 2 - Java

Importing .cer certificate file downloaded from browser (open the url and dig for details) into cacerts keystore in java_home\jre\lib\security worked for me, as opposed to attemps to generate and use my own keystore.

  1. Go to your java_home\jre\lib\security
  2. (Windows) Open admin command line there using cmd and CTRL+SHIFT+ENTER
  3. Run keytool to import certificate:
  • (Replace yourAliasName and path\to\certificate.cer respectively)

 ..\..\bin\keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias yourAliasName -file path\to\certificate.cer

This way you don't have to specify any additional JVM options and the certificate should be recognized by the JRE.

Solution 3 - Java

Here is the code I've been using for programatically importing .cer files into a new KeyStore.

import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
//VERY IMPORTANT.  SOME OF THESE EXIST IN MORE THAN ONE PACKAGE!
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;

//Put everything after here in your function.
KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(null);//Make an empty store
InputStream fis = /* insert your file path here */;
BufferedInputStream bis = new BufferedInputStream(fis);

CertificateFactory cf = CertificateFactory.getInstance("X.509");

while (bis.available() > 0) {
	Certificate cert = cf.generateCertificate(bis);
	trustStore.setCertificateEntry("fiddler"+bis.available(), cert);
}

Solution 4 - Java

You shouldn't have to make any changes to the certificate. Are you sure you are running the right import command?

The following works for me:

keytool -import -alias joe -file mycert.cer -keystore mycerts -storepass changeit

where mycert.cer contains:

-----BEGIN CERTIFICATE-----
MIIFUTCCBDmgAwIBAgIHK4FgDiVqczANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
BhMCVVMxEDAOBgNVBAgTB0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAY
...
RLJKd+SjxhLMD2pznKxC/Ztkkcoxaw9u0zVPOPrUtsE/X68Vmv6AEHJ+lWnUaWlf
zLpfMEvelFPYH4NT9mV5wuQ1Pgurf/ydBhPizc0uOCvd6UddJS5rPfVWnuFkgQOk
WmD+yvuojwsL38LPbtrC8SZgPKT3grnLwKu18nm3UN2isuciKPF2spNEFnmCUWDc
MMicbud3twMSO6Zbm3lx6CToNFzP
-----END CERTIFICATE-----

Solution 5 - Java

An open source GUI tool is available at keystore-explorer.org

> KeyStore Explorer > > KeyStore Explorer is an open source GUI replacement for the Java > command-line utilities keytool and jarsigner. KeyStore Explorer > presents their functionality, and more, via an intuitive graphical > user interface.

Following screens will help (they are from the official site)

Default screen that you get by running the command:

shantha@shantha:~$./Downloads/kse-521/kse.sh

enter image description here

And go to Examine and Examine a URL option and then give the web URL that you want to import.

The result window will be like below if you give google site link. enter image description here

This is one of Use case and rest is up-to the user(all credits go to the keystore-explorer.org)

Solution 6 - Java

The certificate that you already have is probably the server's certificate, or the certificate used to sign the server's certificate. You will need it so that your web service client can authenticate the server.

But if additionally you need to perform client authentication with SSL, then you need to get your own certificate, to authenticate your web service client. For this you need to create a certificate request; the process involves creating your own private key, and the corresponding public key, and attaching that public key along with some of your info (email, name, domain name, etc) to a file that's called the certificate request. Then you send that certificate request to the company that's already asked you for it, and they will create your certificate, by signing your public key with their private key, and they'll send you back an X509 file with your certificate, which you can now add to your keystore, and you'll be ready to connect to a web service using SSL requiring client authentication.

To generate your certificate request, use "keytool -certreq -alias -file -keypass -keystore ". Send the resulting file to the company that's going to sign it.

When you get back your certificate, run "keytool -importcert -alias -keypass -keystore ".

You may need to used -storepass in both cases if the keystore is protected (which is a good idea).

Solution 7 - Java

Here's a script I used to batch import a bunch of crt files in the current directory into the java keystore. Just save this to the same folder as your certificate, and run it like so:

./import_all_certs.sh

###import_all_certs.sh KEYSTORE="$(/usr/libexec/java_home)/jre/lib/security/cacerts";

function running_as_root()
{
  if [ "$EUID" -ne 0 ]
    then echo "NO"
    exit
  fi

  echo "YES"
}

function import_certs_to_java_keystore
{
  for crt in *.crt; do 
    echo prepping $crt 
    keytool -import -file $crt -storepass changeit -noprompt --alias alias__${crt} -keystore $KEYSTORE
    echo 
  done
}

if [ "$(running_as_root)" == "YES" ]
then
  import_certs_to_java_keystore
else
  echo "This script needs to be run as root!"
fi

Solution 8 - Java

Here's how this worked for me:

  1. Save as .txt the certificate data in the following format in a text editor > -----BEGIN CERTIFICATE----- > [data serialized by microsoft] > -----END CERTIFICATE-----
  2. Open chrome browser (this step might work with other browsers too) settings > show advanced settings > HTTPS/SSL > manage certificates Import the .txt in step 1
  3. Select and export that certificate in Base-64 encoded format. Save it as .cer
  4. Now you can use keytool or Portecle to import it to your java keystore

Solution 9 - Java

Although a-lot of good answers have been provided I want to give an alternative for loading the ssl material programatically. You can try out the following snippet:

Path certificatePath = Paths.get("/path/to/certificate.cer");
List<Certificate> certificates = CertificateUtils.loadCertificate(certificatePath);

SSLFactory sslFactory = SSLFactory.builder()
        .withTrustMaterial(certificates)
        .build();

SSLContext sslContext = sslFactory.getSslContext();

It can handle pem, der (binary) and p7b formatted files. This example code snippet is from the library: GitHub - SSLContext Kickstart You can add it with the following snippet:

<dependency>
    <groupId>io.github.hakky54</groupId>
    <artifactId>sslcontext-kickstart</artifactId>
    <version>7.0.2</version>
</dependency>

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJan-PieterView Question on Stackoverflow
Solution 1 - JavalujopView Answer on Stackoverflow
Solution 2 - JavajedizView Answer on Stackoverflow
Solution 3 - JavaPatrick MView Answer on Stackoverflow
Solution 4 - JavadogbaneView Answer on Stackoverflow
Solution 5 - JavaShantha KumaraView Answer on Stackoverflow
Solution 6 - JavaChochosView Answer on Stackoverflow
Solution 7 - JavaBrad ParksView Answer on Stackoverflow
Solution 8 - Javacode4kixView Answer on Stackoverflow
Solution 9 - JavaHakan54View Answer on Stackoverflow