0

I am trying connect to my backend through https. I have 2 certificats *.p12 and *.cer. I'm imported with command(see in code) I imported key with command:

keytool -v -importkeystore -srckeystore bonus-testagent.p12 -srcstoretype PKCS12 -destkeystore truststore.jks -deststoretype JKS

my code is(grails service):

private SSLSocketFactory getSSLFactory() throws Exception {
    KeyStore keyStore = KeyStore.getInstance("JKS");
    String keystoreFile = 'D:\\grails_wide\\certificates\\truststore.jks'
    File binaryFile = new File(keystoreFile);
    InputStream is = binaryFile.newInputStream()
    if (is == null) {
        return null;
    }
    String password = "****";
    keyStore.load(is, password.toCharArray());
    is.close();


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

    SSLContext ctx = SSLContext.getInstance("TLS");
    ctx.init(null, tmf.getTrustManagers(), null);
    return ctx.getSocketFactory();
}

def accountInfo(String cardNumber, Cookie[] cookies) {
    String urlStr = "https://app-domain.com";
    URL url = new URL(urlStr);

    HttpsURLConnection conn = (HttpsURLConnection)url.openConnection();
    conn.setSSLSocketFactory(getSSLFactory());
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Cookie", WebUtils.buildCookiesHeader(cookies))
    InputStream is = conn.getInputStream();
    BufferedReader rd = new BufferedReader(new InputStreamReader(is));
    String line;
    StringBuffer stringBuffer = new StringBuffer();
    while ((line = rd.readLine()) != null) {
        stringBuffer.append(line);
    }
    rd.close();
    def response = stringBuffer.toString();

But it has error:

ERROR errors.GrailsExceptionResolver  - SunCertPathBuilderException occurred when processing request: [POST] /club/account
unable to find valid certification path to requested target. Stacktrace follows:
Message: unable to find valid certification path to requested target

In string:

InputStream is = conn.getInputStream();

1 Answers1

0

Firstly, you generally don't need to convert your PKCS#12 (.p12) file into a JKS store, you can use the PKCS12 keystore type directly.

Secondly, a .p12 file is generally not to be used as a truststore, but as a keysore instead. (See this question for the difference between keystore and truststore, for example.) The .p12 file will contain private key material, which doesn't belong in a truststore.

What you've done here is replacing the default truststore with your .p12 file, so it can only validate against the certificate in your .p12 file when it connects remotely (instead of validating against CA certificates). Hence, it fails with "unable to find valid certification path to requested target".

Presumably, you were trying to connect with a client-certificate. In this case, you'll need to use that .p12 file as a keystore. To do this:

  1. (Optional) If you want to load your .p12 directly, use KeyStore.getInstance("PKCS12") instead. (You wouldn't have needed that keytool conversion.)
  2. Use it with a KeyManagerFactory instead of the TrustManagerFactory. The init password will be the password for the key itself, which is the same as the store key in PKCS#12.
  3. Use ctx.init(kmf.getKeyManagers(), null, null). The second null parameter will use the JRE's default trust store (assuming your server is trusted this way).
Community
  • 1
  • 1
Bruno
  • 119,590
  • 31
  • 270
  • 376