i'm currently working on a small swift-client and got some hard performance issues by downloading files.
After thousands of checks i localized the problem by downloading files through ssl.
Normal downloads(http) works fine without any problems(or performance issues).
But SSL downloads blow up my CPU ... a single core goes up to 100 % load (for a single thread)
i wrote a small testclass without my entire program and can confirm my previous observations.
package testDownload;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.nio.channels.WritableByteChannel;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class Downloader {
public Downloader(boolean sslTrigger) throws IOException {
try {
this.allowSelfSignCerts();
} catch (KeyManagementException | NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
URL url;
// Http Download
if (sslTrigger) {
System.out.println("HTTPS-Mode");
url = new URL("HTTPS LINK");
} else {
System.out.println("HTTP-Mode");
url = new URL("HTTP LINK");
}
URLConnection conn = url.openConnection();
InputStream input = conn.getInputStream();
OutputStream output = new FileOutputStream(new File(System.getProperty("user.home")+System.getProperty("file.separator")+"test.dat"));
ReadableByteChannel inputChannel = Channels.newChannel(input);
WritableByteChannel outputChannel = Channels.newChannel(output);
System.out.println("start download");
this.fastChannelCopy(inputChannel, outputChannel);
inputChannel.close();
outputChannel.close();
System.out.println("finish");
}
private void fastChannelCopy(ReadableByteChannel src, WritableByteChannel dest) throws IOException {
ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024);
while (src.read(buffer) != -1) {
buffer.flip();
dest.write(buffer);
buffer.compact();
}
buffer.flip();
while (buffer.hasRemaining()) {
dest.write(buffer);
}
}
private void allowSelfSignCerts() throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts = new TrustManager[] {new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
}
}
used java-version
java -version
java version "1.8.0_45"
Java(TM) SE Runtime Environment (build 1.8.0_45-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.45-b02, mixed mode)
Has anyone an idea for solving this issue?
Normal downloads(http) works fine without any problems(or performance issues). But SSL downloads blow up my CPU ... a single core goes up to 100 % load (for a single thread)
This might depend on the cipher client and server agreed on. Very common are AES ciphers. But while AES is fast with special hardware and it terrible slow and CPU bound when done in software. Historically hardware acceleration was not available for Java. But it looks like they've added it in Java 8, even though only for the server JVM.
For more information see AES acceleration for Java and AES-NI intrinsics enabled by default?.
Related
I want to start Apache HTTP server in Java.
After a while I found this answer. And did as indicated there.
The KeyStore was created according to this instruction.
My code now:
import me.project.Main;
import org.apache.http.ExceptionLogger;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.bootstrap.HttpServer;
import org.apache.http.impl.bootstrap.ServerBootstrap;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
public class Server {
private static final Logger logger = LoggerFactory.getLogger(Server.class);
private static HttpServer server;
public static void createAndStart() {
if (server != null) return;
SSLContext sslContext = prepareSSLContext();
SocketConfig config = SocketConfig.custom().setSoTimeout(1500).setTcpNoDelay(true).build();
server = ServerBootstrap.bootstrap()
.setListenerPort(43286)
.setServerInfo("Test")
.setSocketConfig(config)
.setSslContext(sslContext)
.setExceptionLogger(ExceptionLogger.STD_ERR)
.registerHandler("/", new HelloPage())
.create();
System.out.println("Ok");
try {
server.start();
} catch (IOException ioException) {
logger.error("Cannot start server: ", ioException);
}
}
private static SSLContext prepareSSLContext() {
URL keyStoreFile = Main.class.getClassLoader().getResource("keystore.jks");
if (keyStoreFile == null) {
logger.error("Key store not found");
System.exit(1);
}
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStoreFile, "mysuperpass".toCharArray(), "mysuperpass".toCharArray()).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException | CertificateException | IOException e) {
logger.error("Cannot init ssl context", e);
}
return sslContext;
}
}
It starts sucessfully and prints "Ok".
But a few things I still don't understand:
It seems to me that this is still SSL protocol, not TLS
How can I make sure that the server really communicates using the encrypted TLS protocol (except to intercept traffic and watch)
How does the loadKeyMaterial (keyStore, storePass, KeyPass) method know which key to take from the store without the key alias?
I found another example of enabling TLS here, but I don't understand where to use the object conn after:
DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1204);
conn.bind(socket);
Sorry, I don't know English well and translated this with Google Translate
It seems to me that this is still SSL protocol, not TLS
The classes were originally implemented for SSL(v3) in the 1990s, but they have implemented TLS since about 2000 (first 1.0, later 1.1 1.2 and now 1.3) while the names have remained the same for compatibility. In fact since 8u31 in 2014 SSLv3 has been disabled by default in the JVM configuration because it was broken by the "POODLE" attack and the 'SSL' classes in fact provide only TLS.
How can I make sure that the server really communicates using the encrypted TLS protocol (except to intercept traffic and watch)
Try connecting to it with TLS and non-TLS tools.
How does the loadKeyMaterial (keyStore, storePass, KeyPass) method know which key to take from the store without the key alias?
It uses the JSSE-default KeyManager which implements chooseServerAlias to return the first key-and-cert entry (i.e. PrivateKeyEntry) it finds that is suitable for a client-enabled ciphersuite -- or for TLS 1.3 where this is no longer in the ciphersuite, a client-enabled sigalg. IIRC 'first' is in a hashmap-defined order which means for practical/human purposes it is arbitrary. But most servers use a keystore that contains only one PrivateKeyEntry so all choice sequences are the same.
I'm new to messing around with APIs (both official and unofficial) and I'm using one called JavaSnap. I've been messing around with a very basic implementation of the example code, but have been running into errors. Here is the very basic code:
Snapchat snapchat = Snapchat.login("xxxx", "xxxxx");
Firstly I ran into loads of ClassNotFound errors and had to keep on downloading apache modules (commons, httpcomponents etc.) to allow the program to progress, but being class files this meant I couldn't see all at once what modules I needed to download. So if anyone wants to tell me how wrong I'm doing something feel free.
Anyway, now having cleared up all the ClassNotFound exceptions (I hope) I'm getting the following exception:
com.mashape.unirest.http.exceptions.UnirestException: javax.net.ssl.SSLPeerUnverifiedException: Host name 'feelinsonice-hrd.appspot.com' does not match the certificate subject provided by the peer (CN=*.appspot.com, O=Google Inc, L=Mountain View, ST=California, C=US)
at com.mashape.unirest.http.HttpClientHelper.request(HttpClientHelper.java:146)
at com.mashape.unirest.request.BaseRequest.asJson(BaseRequest.java:68)
at com.habosa.javasnap.Snapchat.requestJson(Snapchat.java:953)
at com.habosa.javasnap.Snapchat.login(Snapchat.java:160)
at Tester.go(Tester.java:21)
As I understand it, this is because I need to enable trusting all certificates, however to do this I believe I'd need to use HostNameVerifiers with SSLSocketFactorys, but I can't really begin to mess around with this as I only have the source for the JavaSnap API, and tracing the error up the stack the most recent method available for me to edit is this:
private static HttpResponse<JsonNode> requestJson(String path, Map<String, Object> params, File file) throws UnirestException {
MultipartBody req = prepareRequest(path, params, file);
// Execute and return response as JSON
HttpResponse<JsonNode> resp = req.asJson();
// Record
lastRequestPath = path;
lastResponse = resp;
lastResponseBodyClass = JsonNode.class;
return resp;
My question is, am I actually on the right lines with my thinking? If I am how can I achieve my goal of eliminating this error / trusting certificates? If I'm not then what in fact is the problem?
Thanks very much
i answer this old question to remember my search
the certificate error solution is a combination from a few places
https://github.com/Mashape/unirest-java/issues/70, where i started.
http://literatejava.com/networks/ignore-ssl-certificate-errors-apache-httpclient-4-4/ very good explanation.
http://www.baeldung.com/httpclient-ssl, solution for all versions.
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import javax.net.ssl.SSLContext;
import javax.security.cert.CertificateException;
import javax.security.cert.X509Certificate;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.JsonNode;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
public class XXX {
private static HttpClient unsafeHttpClient;
static {
try {
SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustSelfSignedStrategy() {
public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
return true;
}
}).build();
unsafeHttpClient = HttpClients.custom().setSSLContext(sslContext)
.setSSLHostnameVerifier(new NoopHostnameVerifier()).build();
} catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException e) {
e.printStackTrace();
}
}
public static HttpClient getClient() {
return unsafeHttpClient;
}
public static void main(String[] args) {
try {
HttpClient creepyClient = RestUnirestClient.getClient();
Unirest.setHttpClient(creepyClient);
HttpResponse<JsonNode> response = Unirest.get("https://httpbin.org/get?show_env=1").asJson();
System.out.println(response.getBody().toString());
} catch (UnirestException e) {
e.printStackTrace();
}
}
}
I know that to load a certificate to use, I need to call KeyStore.load(InputStream, char[]);. How could I load the certificate on the client side if I need the password? I don't need this when connecting to Google, but I want to use Trust Managers to validate Google certificates. I also cannot make a SSLServerSocket and connect to it without loading a certificate.
EDIT: Added code:
package testing;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
public class SSLClientTest {
public static void main(String[] args) {
int port = 443;
String host = "google.com";
try {
SSLContext sc = SSLContext.getInstance("TLSv1.2");
KeyStore ks = KeyStore.getInstance("JKS");
InputStream ksIs = new FileInputStream("securecert.certificate");
try {
ks.load(ksIs, "pwdpwdpwd".toCharArray());
} finally {
if (ksIs != null) {
ksIs.close();
}
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, "pwdpwdpwd".toCharArray());
sc.init(kmf.getKeyManagers(),
new TrustManager[] { new MyTrustManager() }, null);
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory
.getDefault();
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.startHandshake();
BufferedReader in = new BufferedReader(new InputStreamReader(
socket.getInputStream()));
System.out.println(in.readLine());
in.close();
socket.close();
} catch (Exception e) {
e.printStackTrace();
}
}
private static final class MyTrustManager implements X509TrustManager {
#Override
public void checkClientTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
#Override
public void checkServerTrusted(X509Certificate[] arg0, String arg1)
throws CertificateException {
}
#Override
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[] {};
}
}
}
Note that I have to load the certificate, securecert.certificate, at the like of code ks.load(InputStream, char[]); I of course know the password, but what if I don't? Then how could I validate the certificate with a trust manager? This code simply locks. Please answer. Thanks!
Seems that you need a client authentication through SSL and you want let the user enter the password for his keystore. Based on your explanation I suppose that each installed client has its own keystore from a local path (If not the question has nonsense because if the keystore is always the same you don't need to pass a different password each time... however if this is the case you've to check if this client it's secure).
So to let the user enter a password you can instantiate the keystore in a different way instead of using KeyStore.getInstance(InputStream, Char[]), you can use KeyStore.Builder.newInstance and KeyStore.CallbackHandlerProtection methods, and you have to create a class which implements javax.security.auth.callback.CallbackHandler, this class have to override handle() method for example using swing or awt panel to let the user introduce the password. Below I show you some sample code to guide you through this steps:
Load the keystore
import java.io.File;
import java.security.KeyStore;
import java.security.Provider;
import java.util.Enumeration;
public class KeyStoreCallbackSample {
public static void main(String args[]) throws Exception {
// instantiate a keystore to get the provider for specific type
KeyStore ks = KeyStore.getInstance("JKS");
// create the callback handler to get the password
KeyStore.CallbackHandlerProtection cbhp = new KeyStore.CallbackHandlerProtection(new YourImplementationCallbackHander());
// create the builder passing keystoreType, provider, keystore file, and callbackhandler
KeyStore.Builder builder = KeyStore.Builder.newInstance("JKS", ks.getProvider(), new File("/path/YourKeyStore.jks"), cbhp);
// create the keystore
ks = builder.getKeyStore();
// print the keystores alias to check if all it's load correctly
Enumeration<String> aliases = ks.aliases();
while(aliases.hasMoreElements()){
System.out.println(aliases.nextElement());
}
}
}
CallbackHandler implementation
import java.io.IOException;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
/**
* PIN handler for keystores
*/
public class PinInputHandler implements CallbackHandler {
private char[] lastPassword;
public PinInputHandler(){}
// implement this method to handle the callback
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback cb : callbacks) {
if (cb instanceof javax.security.auth.callback.PasswordCallback) {
javax.security.auth.callback.PasswordCallback pcb = (javax.security.auth.callback.PasswordCallback) cb;
try {
this.lastPassword = // HERE YOUR SWING OR AWT OR ANOTHER WAY TO GET THE PASSWORD FROM THE CLIENT
} catch (Exception e) {}
pcb.setPassword(this.lastPassword);
}
}
}
}
If you need more info you can check at KeyStore, KeyStore.Builder, KeyStore.CallbackHandlerProtection and CallbackHandlerdocumentation.
Hope this helps,
I would like to be able to get access to all trusted root certificates programmatically in a Java app.
I was looking at the keystore interface, but I'm hoping to get the list of trusted roots that's implicit with the JRE.
Is this accessible anywhere?
There's an example that shows how to get a Set of the root certificates and iterate through them called Listing the Most-Trusted Certificate Authorities (CA) in a Key Store. Here's a slightly modified version that prints out each certificate (tested on Windows Vista).
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.PKIXParameters;
import java.security.cert.TrustAnchor;
import java.security.cert.X509Certificate;
import java.util.Iterator;
public class Main {
public static void main(String[] args) {
try {
// Load the JDK's cacerts keystore file
String filename = System.getProperty("java.home") + "/lib/security/cacerts".replace('/', File.separatorChar);
FileInputStream is = new FileInputStream(filename);
KeyStore keystore = KeyStore.getInstance(KeyStore.getDefaultType());
String password = "changeit";
keystore.load(is, password.toCharArray());
// This class retrieves the most-trusted CAs from the keystore
PKIXParameters params = new PKIXParameters(keystore);
// Get the set of trust anchors, which contain the most-trusted CA certificates
Iterator it = params.getTrustAnchors().iterator();
while( it.hasNext() ) {
TrustAnchor ta = (TrustAnchor)it.next();
// Get certificate
X509Certificate cert = ta.getTrustedCert();
System.out.println(cert);
}
} catch (CertificateException e) {
} catch (KeyStoreException e) {
} catch (NoSuchAlgorithmException e) {
} catch (InvalidAlgorithmParameterException e) {
} catch (IOException e) {
}
}
}
This should be more flexible using the default trust store in the system to get all certificates:
TrustManagerFactory trustManagerFactory =
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
List<Certificate> x509Certificates = new ArrayList<>();
trustManagerFactory.init((KeyStore)null);
Arrays.asList(trustManagerFactory.getTrustManagers()).stream().forEach(t -> {
x509Certificates.addAll(Arrays.asList(((X509TrustManager)t).getAcceptedIssuers()));
});
```
A working example, combining concept from Bill the Lizard and k_o_ answer:
import java.io.FileInputStream;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.KeyStore;
import java.security.cert.X509Certificate;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class JDKTrustStoreCertListing {
public static void main(String[] args) throws Exception{
String javaHome=System.getProperty("java.home");
Path jdkCACertPath=Paths.get(javaHome, "lib", "security", "cacerts");
TrustManagerFactory trustManagerFactory=TrustManagerFactory
.getInstance(TrustManagerFactory
.getDefaultAlgorithm());
FileInputStream fis=new FileInputStream(jdkCACertPath.toFile());
String keystorePassword="changeit";
KeyStore keyStore=KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(fis, keystorePassword.toCharArray());
fis.close();
trustManagerFactory.init(keyStore);
TrustManager[] truestManagers=trustManagerFactory.getTrustManagers();
for(TrustManager t:truestManagers)
for(X509Certificate c:((X509TrustManager)t).getAcceptedIssuers())
System.out.println(c.getIssuerX500Principal());
}//main closing
}//class closing
I'm accessing an internal database using MATLAB's urlread command, everything was working fine until the service was moved to a secure server (i.e. with an HTTPS address rather than an HTTP address). Now urlread no longer successfully retrieves results. It gives an error:
Error downloading URL. Your network connection may be down or your proxy settings improperly configured.
I believe the problem is that the service is using an invalid digital certificate since if I try to access the resource directly in a web browser I get "untrusted connection" warning which I am able to pass through by adding the site to an Exception list. urlread doesn't have an obvious way of handling this problem.
Under the hood urlread is using Java to access web resources, and the error is thrown at this line:
inputStream = urlConnection.getInputStream;
where urlConnection is a Java object: sun.net.www.protocol.https.HttpsURLConnectionImpl.
Anyone suggest a workaround for this problem?
Consider the following Java class. Borrowing from this code: Disabling Certificate Validation in an HTTPS Connection
C:\MATLAB\MyJavaClasses\com\stackoverflow\Downloader.java
package com.stackoverflow;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.cert.X509Certificate;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import javax.net.ssl.HostnameVerifier;
public class Downloader {
public static String getData(String address) throws Exception {
// Create a trust manager that does not validate certificate chains
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return null;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
}
}
};
// Create a host name verifier that always passes
HostnameVerifier allHostsValid = new HostnameVerifier() {
public boolean verify(String hostname, SSLSession session) {
return true;
}
};
// Install the all-trusting trust manager
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, new java.security.SecureRandom());
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
// Install the all-trusting host verifier
HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
// open connection
URL page = new URL(address);
HttpURLConnection conn = (HttpURLConnection) page.openConnection();
BufferedReader buff = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// read text
String line;
StringBuffer text = new StringBuffer();
while ( (line = buff.readLine()) != null ) {
//System.out.println(line);
text.append(line + "\n");
}
buff.close();
return text.toString();
}
public static void main(String[] argv) throws Exception {
String str = getData("https://expired.badssl.com/");
System.out.println(str);
}
}
MATLAB
First we compile the Java class (we must use a JDK version compatible with MATLAB):
>> version -java
>> system('javac C:\MATLAB\MyJavaClasses\com\stackoverflow\Downloader.java');
Next we instantiate and use it MATLAB as:
javaaddpath('C:\MATLAB\MyJavaClasses')
dl = com.stackoverflow.Downloader;
str = char(dl.getData('https://expired.badssl.com/'));
web(['text://' str], '-new')
Here are a few URLs with bad SSL certificates to test:
urls = {
'https://expired.badssl.com/' % expired
'https://wrong.host.badssl.com/' % wrong host
'https://self-signed.badssl.com/' % self-signed
'https://revoked.grc.com/' % revoked
};
UPDATE: I should mention that starting with R2014b, MATLAB has a new function webread that supersedes urlread.
thanks for the solution. It worked, however, sometimes, I had received the following exception "java.io.IOException: The issuer can not be found in the trusted CA list." and I was not able to get rid of this error.
Therefore, I tried an alternative solution that works well. You can use the following Java code in Matlab function:
function str = ReadUrl(url)
is = java.net.URL([], url, sun.net.www.protocol.https.Handler).openConnection().getInputStream();
br = java.io.BufferedReader(java.io.InputStreamReader(is));
str = char(br.readLine());
end
Best,
Jan
Note also that the "canonical" way to solve this issue is to import the certificate into MATLAB's keystore (i.e., not your JVM's keystore).
This is documented here: Mathworks on using untrusted SSL certificates.