0

I am fairly ignorant regarding certificates, and would appreciate any guidance as to what I do wrong... Unfortunately I wasn't able to find a solution on the rest of StackOverflow or elsewhere on the web.

I have a URL (using HTTPS) from which I should get the response. (An image in my case, but I'm sure that's less important.)

Here's what I did:

1. Accessing URL from web browser

It response with HTTP code 403 "Forbidden".

I am given a certificate (*.pfx file) which is needed to access the URL.

2. Installing certificate and trying again from browser

Double-clicking on the PFX file opens the "Certificate Import Wizard" (Windows 10). Follow along, then reboot.

Now Chrome retrieves the resource fine. Firefox still shows a 403, so under Options > Advanced > Certificates > View Certificates I import the PFX. Now FF also returns the resource fine.

3. Installing certificate under JVM

I now want to call the same URL using Java. I'm still on Java 7 for this project for legacy purposes. I understand the cert should be imported into the Java keystore using the keytool CLI command. However this command wants a cert in DER X509 format. So I export the cert again from Chrome into this format.

Now run the command: keytool -import -alias MY_ALIAS -keystore C:/PROGRA~1/Java/jdk1.7.0_80/jre/lib/security/cacerts -file my_cert.cer

Do keytool -list -v -keystore C:/PROGRA~1/Java/jdk1.7.0_80/jre/lib/security/cacerts and inspect for inclusion of required cert.

Now I run my Java program:

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLConnection;

public class TestUrlRead {    
    private static final String PROXY_URL   = ...;
    private static final int    PROXY_PORT  = ...;
    private static final String IMAGE_URL   = ...;

    public static void main(String[] args) throws Exception {
        Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress(PROXY_URL, PROXY_PORT));
        URL url = new URL(IMAGE_URL);
        URLConnection con = url.openConnection(proxy);
        con.setDoOutput(true);
        con.connect();
        InputStream webIn = con.getInputStream(); // <-- causes IOException
        // read and use webIn
        inReader.close();
    }
}

The exception thrown is:

Exception in thread "main" java.io.IOException: Server returned HTTP response code: 403 for URL: ...
    at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1627)
    at sun.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:254)
    at TestUrlRead.main(TestUrlRead.java:33)

The response and timing suggest that this is similar to the browser without certificate. What am I doing wrong?

frIT
  • 3,213
  • 1
  • 18
  • 22
  • You need to configure the keystore for the UrlConnection. See https://stackoverflow.com/questions/3734613/how-to-request-a-url-that-requires-a-client-certificate-for-authentication – pedrofb Aug 14 '17 at 06:47

1 Answers1

0

I export the cert again from Chrome into this format.

At this point you lost the private key that was contained in the .pfx file, so you were unable to send a certificate to the server. You should have imported the .pfx file directly as a keystore of its own, type PKCS12, or indeed just use it directly via javax.net.ssl.keyStore/keyStoreType/keyStorePassword. See this question for how to do that.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • I didn't understand the aspect about private keys being included in the PFX but not in the CER file. I was able to run my sample code by pointing to the original PFX file of type PKCS12, thanks to your suggestion. – frIT Aug 14 '17 at 08:45
  • 1
    Well it is as simple as this: private keys are included in the PFX but not in the CER file. The PFX file is a keystore, the CER file only a certificate. A certificate is a wrapper for a public key. The private key is separate. – user207421 Aug 14 '17 at 08:46