Image download: java certificate error

Hello everyone!

I have some code that downloads images from external servers, and it has always worked great… until now. It appears that there is an issue with their java certificate and I’ve been trying find a work around. I’ve tried adding the URL to my java control panel exception site list, to no effect. The only other solutions I’ve found involve java’s keystore and truststore. However, those methods are a bit beyond me and all of the instructions I’ve found are not written for those that have never heard of them before…

You can see from the example code below that errors will be thrown, but you can paste the image URL into your browser and it will work (though sometimes I’ve seen a security warning pop up).

Does anyone know of a way around this? I’d very much like to solve this purely with code in the sketch, if possible… The real program is running on another machine that is only be used for this program and must remain online.

static final String LINK =
  "https://so2.gsfc.nasa.gov/so2_files/vitali_clickable_map4e.jpg";

static final String EXT = "jpg";

PImage photo;

void settings() {
  photo = loadImage(LINK, EXT);
  size(photo.width, photo.height);
  noLoop();
}

void draw() {
  set(0, 0, photo);
}

And the errors:

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
	at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
	at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1949)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:302)
	at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:296)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1509)
	at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:216)
	at sun.security.ssl.Handshaker.processLoop(Handshaker.java:979)
	at sun.security.ssl.Handshaker.process_record(Handshaker.java:914)
	at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1062)
	at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1375)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1403)
	at sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1387)
	at sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:559)
	at sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:185)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream0(HttpURLConnection.java:1513)
	at sun.net.www.protocol.http.HttpURLConnection.getInputStream(HttpURLConnection.java:1441)
	at java.net.HttpURLConnection.getResponseCode(HttpURLConnection.java:480)
	at sun.net.www.protocol.https.HttpsURLConnectionImpl.getResponseCode(HttpsURLConnectionImpl.java:338)
	at processing.core.PApplet.createInputRaw(PApplet.java:6737)
	at processing.core.PApplet.createInput(PApplet.java:6695)
	at processing.core.PApplet.loadBytes(PApplet.java:6914)
	at processing.core.PApplet.loadImage(PApplet.java:5293)
	at climate_download_problem_testing.settings(climate_download_problem_testing.java:25)
	at processing.core.PApplet.handleSettings(PApplet.java:962)
	at processing.core.PApplet.runSketch(PApplet.java:10248)
	at processing.core.PApplet.main(PApplet.java:10008)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:387)
	at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:230)
	at sun.security.validator.Validator.validate(Validator.java:260)
	at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
	at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:229)
	at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:124)
	at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1491)
	... 21 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
	at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141)
	at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126)
	at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
	at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
	... 27 more
The file "https://so2.gsfc.nasa.gov/so2_files/vitali_clickable_map4e.jpg" is missing or inaccessible, make sure the URL is valid or that the file has been added to your sketch and is readable.

I think you have some syntax errors: loadImage() doesn’t require a separate extension and I used image(photo,0,0) instead of set(). The following works on my system (MacOS).

static final String LINK =
  "https://so2.gsfc.nasa.gov/so2_files/vitali_clickable_map4e.jpg";

PImage photo;

void settings() {
  photo = loadImage(LINK);
  size(photo.width, photo.height);
  noLoop();
}

void draw() {
  image(photo,0,0);
}

Thank you svan! Unfortunately, I get the same errors. And I get these errors on two seperate windows 10 machines.

Sounds like a Windows 10 problem.

Maybe, well I hope to work past it somehow.

I’ve come back around to this problem. No progress yet so I’m hoping someone might have a new idea.

Hi @jetjaguar,

looks like the used server root certificate is missing in the java keystore, hence the ssl could not be verified.

To solve this you need to download the certificate from the server (possible by browser. Klick on the lock and show certificates and download)

Afterwards you can add it to cacerts by openssl keytool.

Cheers
— mnse

PS: can’t test it now as currently have only mobile access. Will have a closer look tomorrow…

1 Like

Hi @jetjaguar,

I’ve tried it with processing 3.5.4 and 4beta and everything runs fine on my win10 box. Means also, that the shipped cacerts should be sufficient, as I’ve not making changes and uses it out of the box.
So either you are using a different java version than shipped or there is something suspicious going on
To solve it we need to dig a bit deeper…

If you like you can change this in your setting and look whats ongoing …

void settings() {
// prints your java settings on startup
  java.util.Iterator it = System.getProperties().entrySet().iterator();
  while (it.hasNext()) {
    java.util.Map.Entry<String, String> pair = (java.util.Map.Entry<String, String>) it.next();
    println(pair.getKey() + " => " + pair.getValue());
  }  

// prints network info during call
  System.setProperty("javax.net.debug", "all");

  photo = loadImage(LINK);
  size(photo.width, photo.height);
  noLoop();
}

You should find something like this in the trace

Found trusted certificate:
[
[
Version: V3
Subject: CN=ISRG Root X1, O=Internet Security Research Group, C=US
Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11

Cheers
— mnse

PS: Maybe you need to increase the console lines in your %APPDATA%\Roaming\Processing\preferences.txt (PDE must not be running for this)
ie:
console.chars=9000000
console.scrollback.chars=9000000
console.scrollback.lines=999999

Let me know what it shows on your side …

1 Like

Wow, changing the prefs file worked! I went ahead and did that after trying your code because the results in the console were so long that I was suspecious…

I wonder why I had this problem to begin with, and no one else did. It used to work with my code just fine, then one day it didn’t.

This is fantastic, thank you so much mnse!

Found trusted certificate:
[
[
  Version: V3
  Subject: CN=ISRG Root X1, O=Internet Security Research Group, C=US
  Signature Algorithm: SHA256withRSA, OID = 1.2.840.113549.1.1.11