How to import a .cer certificate into a java keystore?
Asked Answered
P

11

314

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.

Pretense answered 1/12, 2010 at 14:18 Comment(0)
S
448
  • 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" 
    
Salazar answered 1/12, 2010 at 16:10 Comment(12)
.CER files do have the public key. They don't have the private key. Suggest editing..Virtual
You are true, I made the original response fast and I make a typing mistake and no one has argued until you. I've corrected and added some little extra information.Salazar
What does -alias do here ?Heather
Java keystore file may have few certificates in one file. The all are identified by -alias attribute. It's a friendly name for your cert in keystoreCub
:( --> keytool error: java.lang.Exception: Input not an X.509 certificatePhenica
necromancer, did you find a solution for the "not an X.509 certificate"Uuge
@Heather A java keystore can have multiple certificates each one with a different alias to identify it. You can use it as reference to identify it and/or to retrieve it programatically by alias name.Salazar
I followed this process and it worked. I then used the outputted keystore to sign my APK. But, the Google store still rejected the APK saying it doesn't match the fingerprint that they gave me. How can I manually check the fingerprint on the outputted file?Calculous
Somehow unrelated doubt. I have written java client & python server communicating over SSL. I used python SSLSocket and java SSLSocket. General description of SSL says in most SSL implementations, client creates a session key & sends it to the server. Further communication works using session key. [continued...]Tempo
[...continuted] But when I read docs of java/python classes, it does not say anything like this. The question is does those classes implement the session key under the hood and use it, or I have to generate them explicitly?Tempo
How can we import a certificate to a keystore using java programNette
I would have liked to submit this edit - but system rejects me due to a "queue full": "If you really were able to authenticate then is because you already had imported the private key."Paigepaik
Q
152

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.

Quimper answered 1/12, 2010 at 14:18 Comment(5)
path\to\cert. If my file is on the desktop how can I path it? C:/user/desktop/ or ../../../../desktop/filenameOsugi
on MacOS /Linux this command works with sudo. Thanks. but what is noprompt param ? I didn't use it and still succeeded.Acculturize
Note that when using the JDK for developing, the correct path is java_home\jdk_x.xx\jre\lib\security For an absolute path use backslash, e.g. "C:\myCert.crt" Quotation marks are optional if the path does not contain whitespaces.Apostrophe
Thanks a million times.Bergess
Question: What about the private key? The discussion is about client certificates. My understanding is that one needs create a CSR with a private key, then receive a client certificate from the remote website company and then match the client certificate to the private key. Your answer does not seem to mention anything about the private key. Just asking.Meit
C
67

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);
}
Champ answered 17/9, 2012 at 5:49 Comment(0)
H
28

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-----
Heterothallic answered 1/12, 2010 at 14:53 Comment(3)
When I try to import the unmodified certificate into the keystore, I get the error "keytool error: java.lang.Exception: Input not an X.509 certificate". After modifying the certificate in the way I described in my post, I am able to import the certificate without errors with a command similar to yours. However it is imported as a trustedCertEntry and is not used when accessing the webservice.Pretense
Can you please add the command the exception to the question? Are you sure you are specifying an alias in your import command?Heterothallic
Don't forget to run cmd as admin if you are using WindowsConsecrate
K
22

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)

Kernel answered 27/11, 2017 at 6:41 Comment(4)
ironically, the provided link leads to a not certified http - no s - site.Jackqueline
@MartinMeeser, the site is their official one and my recommendation is not to share any sensitive or personal information when you refer it.Kernel
The link is now 'https'. Also, the option seems to be 'Examine SSL' in the latest versions.Bavardage
This GUI tool rocks! This answer should be higher up.Yielding
E
8

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).

Ecumenicity answered 1/12, 2010 at 16:21 Comment(0)
N
7

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
Neuro answered 2/3, 2017 at 18:47 Comment(1)
A single line sample of something like that: sudo for FILE in /usr/share/ca-certificates/mozilla/*.crt; do keytool -import -file ${FILE} -storepass password -noprompt --alias "$(basename ${FILE})" -keystore cacerts ; doneSteeplechase
A
1

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
Asis answered 25/9, 2015 at 19:40 Comment(0)
M
1

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>
Michelemichelina answered 24/10, 2021 at 21:28 Comment(0)
A
0

Easy extraction of server certificate could be done with InstallCert2

For installation of server certificate into Java keystore you could use any of keytool examples above.

Ardith answered 18/6, 2023 at 17:3 Comment(0)
C
0

Example for java 21 on Linux:

sudo keytool -importcert -file certificate_downloaded_from_browser -alias myAlias -keystore /usr/lib/jvm/java-21-amazon-corretto/lib/security/cacerts

Cataclysmic answered 12/1 at 16:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.