Christopher Schultz
Christopher Schultz

Reputation: 20862

Is it possible to programmatically provide a Java KeyStore and TrustStore to Connector/J?

I'd like to connect to a MySQL/MariaDB RDBMS using Connector/J (or another compatible driver) and provide the keystore and truststore directly to the driver, rather than supplying a filename for an on-disk keystore/truststore.

I'm not storing my keys and certificates on the disk any longer and I'd like to avoid having to drop them into a temporary file just for this purpose.

Upvotes: 2

Views: 794

Answers (4)

Nur Hasan Masum
Nur Hasan Masum

Reputation: 1

Yes, it's possible to programmatically provide a Java KeyStore and TrustStore to Connector/J. You can use the java.security.KeyStore and java.security.TrustStore classes to create the keystore and truststore in memory, and then pass them to the Connector/J Driver and Connection classes via the javax.net.ssl.keyStore and javax.net.ssl.trustStore system properties, respectively. HERE IS A CODE SAMPLE

import java.io.ByteArrayInputStream;
import java.security.KeyStore;
import java.security.cert.CertificateFactory;

// ...

// Load the keystore and truststore data into memory
byte[] keystoreData = ...;
byte[] truststoreData = ...;

// Create the keystore and truststore objects
KeyStore keyStore = KeyStore.getInstance("JKS");
KeyStore trustStore = KeyStore.getInstance("JKS");
keyStore.load(new ByteArrayInputStream(keystoreData), keystorePassword);
trustStore.load(new ByteArrayInputStream(truststoreData), truststorePassword);

// Set the system properties to use the in-memory keystore and truststore
System.setProperty("javax.net.ssl.keyStore", keyStore);
System.setProperty("javax.net.ssl.trustStore", trustStore);

// Connect to the database using Connector/J
Class.forName("com.mysql.cj.jdbc.Driver");
Connection connection = DriverManager.getConnection(url, username, password);

Upvotes: -2

Christopher Schultz
Christopher Schultz

Reputation: 20862

There may be another option.

I re-read the configuration reference for Connector/J and there is a URL property that can be specified for connections: socketFactory. This must be the fully-qualified name of a class which implements Connector/J's interface called SocketFactory (note that this is similar but unrelated to the standard library class javax.net.SocketFactory).

This interface is pretty small:

public interface SocketFaactory {
    Socket afterHandshake() throws SocketException, IOException;
    Socket beforeHandshake() throws SocketException, IOException;
    Socket connect(String host, int portNumber, Properties props) throws SocketException, IOException;
}

Later versions of the driver add a fourth int loginTimeout parameter to the connect method.

At any rate, it looks like this might be the basis for a solution.

Unfortunately, MySQL does not use vanilla TLS connections so it might not be as simple as returning a Socket from a standard customized javax.net.ssl.SSLSocketFactory.

UPDATE

The SSL/TLS magic happens after connection due to the way MySQL manages its protocol (it's not just plain-TLS).

In the 5.1-era drivers, it's done in a class called ExportControlled in a method called getSSLSocketFactoryDefaultOrConfigured. In later versions (I have 8.0-era source in front of me), it's done in the same class but in a different method called performTlsHandshake.

Without significant hacking of the driver source or re-implementation of a ton of code, I suspect that the better solution is to implement the URL-based keystore-loading from this answer.

Upvotes: 1

Christopher Schultz
Christopher Schultz

Reputation: 20862

I think it is possible, if you are willing to go through a log of hoops to make it happen.

Because e.g. clientCertificateKeyStoreUrl will accept a URL, you can supply it one with a custom protocol handler, like mykeysupplier://mykey.

You can write a custom URLConnection class for mekeysupplier and then return whatever bytes you want from the getInputStream() method. You have to register a protocol handler and stuff like that, too.

So, it's kind of horrifically ugly, but I think it can be made to work and will surely try at least a PoC of this idea, because it will likely solve my problem (I posted the original question).

Upvotes: 2

Setop
Setop

Reputation: 2500

This answer seems to be no. As the way to configure KeyStore and TrustStore is by providing an URL, not a class/factory.

Upvotes: 1

Related Questions