Client has given 2 certificates in '.txt' format and I need to add these certificates during runtime while invoking the SOAP service. Unable to add '.txt' format files as i am getting like 'Invalid Format'. Certificates have "-----BEGIN CERTIFICATE-----" and "-----END CERTIFICATE-----" headers at the top and bottom of the txt file, so it's PEM type file (I assume). Any help/suggestion would be appreciable.
Getting below exception ::
Exception in thread "main" java.io.IOException: Invalid keystore format
Using below code..
public KeyManagerFactory getKeyManagerFactory() throws UnrecoverableKeyException, CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException {
InputStream inputStream = null;
KeyStore ts = null;
KeyManagerFactory keyManagerFactory = null;
try {
ts = KeyStore.getInstance("JKS");
inputStream = this.getClass().getClassLoader().getResourceAsStream("publicCert.txt");
ts.load(inputStream, null);
keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ts, null);
} catch (Exception e) {
throw e;
} finally {
try {
inputStream.close();
} catch (Exception e) {
throw e;
}
}
return keyManagerFactory;
}
After getting the answer, used below code and it's working
rootInterIS = new FileInputStream("rootIntermediaryCertificate.txt");
domainIS = new FileInputStream("domainCertificate.txt");
keystore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(null);
CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
X509Certificate rootInterCert = (X509Certificate) certFactory.generateCertificate(rootInterIS);
X509Certificate domainCert = (X509Certificate) certFactory.generateCertificate(domainIS);
keystore.setCertificateEntry("domainCertificate", domainCert);
keystore.setCertificateEntry("rootInterCe", rootInterrtificateCert);
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(keystore);
PEM format consists of a line ----BEGIN x-----
for one or more words x
, one or more lines of base64 containing data with an internal structure matching x
, and a matching END
line. While someone could create a bogus file with correct BEGIN/END lines but wrong base64, unless they're actively trying to cause you trouble a file that looks like you describe most likely is a PEM certificate.
A certificate (in PEM format) is not a keystore and in particular not JKS. Java supports several different keystore formats, none of which is PEM and none of which is limited to certificates. Use KeyStore.getInstance(type)
only to read a keystore, which you don't have; use CertificateFactory.getInstance("X.509")
to read a certificate file (actually in either PEM or binary aka DER, but at the moment you only care about the former).
In SSL/TLS the KeyManager
is used only for a certificate(s) that authenticates (proves) your own identity with a privatekey, which you don't have. Putting a certificate without privatekey as you have in a KeyManager
will be totally useless and ineffective. If someone has given you only a cert(s) not privatekey to connect to their system, that should be a cert(s) to authenticate their system, not yours; ask the supplier or look at the file(s) to confirm this. Given Java, you can use keytool -printcert -file $file
to see the details of a cert.
You need to put that cert(s) in the TrustManager
instead. Note both KeyManager
and TrustManager
use KeyStore
objects, but in different ways for different purposes. So you create an in-memory empty KeyStore
(do .getInstance(type)
then .load(null)
), add the cert from above to it as a 'trusted' cert, and pass that to the TrustManagerFactory
, and then use the resulting TrustManager
in your SSLContext
etc.