1

I'm trying to accept my SSL certificate for API tests. For that, I exported my certificate with IE (with the second option : x.509 binary encod base 64 (*.cer) I added it in the keystore with this command line :

 keytool -importcert -file certificate.cer -keystore "C:\Program
 Files\Java\jdk1.8.0_111\jre\lib\security\cacerts" -alias "certificatealias"

To list keystore and check if I have my certificate entry, I use this command line :

keytool -list -v -keystore "C:\Program
     Files\Java\jdk1.8.0_111\jre\lib\security\cacerts"  > java_cacerts.txt

I have my certificate entry inside :

Nom d'alias : certificatealias Date de création : 6 déc. 2016 Type d'entrée : trustedCertEntry

Propriétaire : CN=Test, O=Test Emetteur : CN=Test, O=Test Numéro de série : XXXX Valide du : xxx au : xxxx

Empreintes du certificat : MD5: Xxxxxx SHA1 :xxxx SHA256 : XXXX

Nom de l'algorithme de signature : SHA256withRSA Version : 3

In my code, I have :

FileInputStream in = new FileInputStream("certificate.jks");
BufferedInputStream bis = new BufferedInputStream(in);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(bis, "changeit".toCharArray());

Enumeration<String> aliases = ks.aliases();
while (aliases.hasMoreElements()) {
    String alias = aliases.nextElement();
    System.out.println("alias: " + alias);
    System.out.println("bis.available: " +bis.available());
    System.out.println("bis: "+ bis.toString());

    CertificateFactory cf = CertificateFactory.getInstance("X.509");
    X509Certificate x509 = (X509Certificate) cf.generateCertificate(bis);
    KeyStore.Entry newEntry = new KeyStore.TrustedCertificateEntry(x509);
    ks.setEntry("certificatealias", newEntry, null);
}

I received an error :

java.security.cert.CertificateException: Could not parse certificate: java.io.IOException: Empty input

In my console I have :

alias: certificatealias

bis.available: 0
bis: java.io.BufferedInputStream@8xx9d4

The error is on cf.generateCertificate(bis).

Why I have this error? cf and bis are not null or empty...

I saw it can be the keystore type that can be wrong (see the post 3 years ago). KeyStore.getDefaultType() return JKS. That should be good, isn't ? I've checked with the command line : keytool -list -keystore <keystore_location> I've the type :

Type de fichier de clés : JKS

Fournisseur de fichier de clés : SUN

Any hint will be very helpful!

7
  • 1
    You have your keystore loaded in your bis input stream. You can't use that create a certificate out of it, because it is the whole keystore. If you need to get the certificate object and add it to your keystore, you should load the certificate using input stream (like you did for the keystore), and feed that input stream to the generateCertificate method. You could use input stream like FileInputStream to load the certificate. Commented Dec 7, 2016 at 14:51
  • thanks for your help. I added these lines : FileInputStream certificate = new FileInputStream("certificate.cer"); BufferedInputStream bis2 = new BufferedInputStream(certificate); and corrected the line to cf.generateCertificate(bis2);` However, I get another error javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target Commented Dec 7, 2016 at 14:58
  • You may not be having the complete certificate chain in your truststore. Commented Dec 7, 2016 at 15:13
  • When I print the cf.generateCertificate(bis2) I have : `cert: [ [ Version: V3 Subject: CN=Test, O=Test Signature Algorithm: SHA256withRSA, OID = XX Key: Sun RSA public key, 1024 bits modulus: XX (too long) public exponent: xx Validity: [From: X To: X Issuer: CN=Test, O=Test SerialNumber: [ xx] ] Algorithm: [SHA256withRSA] Signature: XX (too long) ] ' Commented Dec 7, 2016 at 15:16
  • Looks like it is a test certificate, you should the whole chain to your cacert keystore to make it work. If you are using dynamic approach of creating the truststore with the certificates that are needed to make the connection, you need to create a custom SSLSocketFactory, you can refer to this post stackoverflow.com/questions/40875264/…. And before your call, you could do HttpsURLConnection.setDefaultSSLSocketFactory(sslSocketFactory); Commented Dec 7, 2016 at 15:21

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.