diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java
index 8eb7eee9f4cb23f8a66b26063c99d6128fdd41e4..fb4900d225ed83d5938d5a47001600040443c161 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java
@@ -39,17 +39,37 @@ class CaseDatabaseFactory {
 	private static final Logger logger = Logger.getLogger(CaseDatabaseFactory.class.getName());
 	private final SQLHelper dbQueryHelper;
 	private final DbCreationHelper dbCreationHelper;
-	
-	// ssl=true: enables SSL encryption. 
-	// DefaultJavaSSLFactory: uses Java's default truststore to validate server certificate.
-	// sslmode=verify-ca: verifies that the server we are connecting to is trusted by CA. 
-	final static String SSL_VERIFY_URL = "?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca";
-	
+		
 	// ssl=true: enables SSL encryption. 
 	// NonValidatingFactory avoids hostname verification.
 	// sslmode=require: This mode makes the encryption mandatory and also requires the connection to fail if it can't be encrypted. 
 	// In this mode, the JDBC driver accepts all server certificates, including self-signed ones.
 	final static String SSL_NONVERIFY_URL = "?ssl=true&sslfactory=org.postgresql.ssl.NonValidatingFactory&sslmode=require";
+	
+	// ssl=true: enables SSL encryption. 
+	// DefaultJavaSSLFactory: uses Java's default truststore to validate server certificate.
+	// sslmode=verify-ca: verifies that the server we are connecting to is trusted by CA. 
+	final static String SSL_VERIFY_DEFAULT_URL = "?ssl=true&sslfactory=org.postgresql.ssl.DefaultJavaSSLFactory&sslmode=verify-ca";
+
+	/**
+	 * Creates JDBC URL string for implementations that use custom keystore to
+	 * validate PostgreSQL CA-signed SSL certificates. The class that performs
+	 * SSL certificate validation must extend org.postgresql.ssl.WrappedFactory
+	 * and generally must follow the same logic.
+	 *
+	 * ssl=true: enables SSL encryption. sslmode=verify-ca: verifies that the
+	 * server we are connecting to is trusted by CA.
+	 *
+	 * @param customSslValidationClassName full canonical name of a Java class
+	 *                                     that performs custom SSL certificate
+	 *                                     validation.
+	 *
+	 * @return JDBS URL string used to connect to PosgreSQL server via CA-signed
+	 *         SSL certificate.
+	 */
+	static String getCustomPostrgesSslVerificationUrl(String customSslValidationClassName) {
+		return "?ssl=true&sslfactory=" + customSslValidationClassName + "&sslmode=verify-ca";
+	}
 		
 	/**
 	 * Create a new SQLite case
@@ -726,7 +746,12 @@ Connection getConnection(String databaseName) throws TskCoreException {
 			
 			if (info.isSslEnabled()) {				
 				if (info.isSslVerify()) {
-					url.append(SSL_VERIFY_URL);
+					if (info.getCustomSslValidationClassName().isBlank()) {
+						url.append(SSL_VERIFY_DEFAULT_URL);
+					} else {
+						// use custom SSL certificate validation class
+						url.append(getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName()));
+					}
 				} else {
 					url.append(SSL_NONVERIFY_URL);
 				}
diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java
index 4cf918dfe5aabdf60e745f1350b137b7d1df478e..2aa4d17ca475a0815e911b2caaa85908ab6d0911 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/CaseDbConnectionInfo.java
@@ -36,6 +36,7 @@ public class CaseDbConnectionInfo {
 	private DbType dbType;
 	private boolean sslEnabled = false;
 	private boolean sslVerify = false;
+	private String customSslValidationClassName;
 
 	/**
 	 * The intent of this class is to hold any information needed to connect to
@@ -62,6 +63,7 @@ public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userN
 			throw new IllegalArgumentException("SQLite database type invalid for CaseDbConnectionInfo. CaseDbConnectionInfo should be used only for remote database types.");
 		}
 		this.dbType = dbType;
+		this.customSslValidationClassName = "";
 	}
 	 
 	/**
@@ -80,8 +82,11 @@ public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userN
 	 * @param dbType       the database type
 	 * @param sslEnabled   a flag whether SSL is enabled
 	 * @param sslVerify   'true' if SSL certificate needs to be CA verified. 'false' if self-signed certificates should be accepted.
+	 * @param customSslValidationClassName full canonical name of a Java class
+	 *                                     that performs custom SSL certificate
+	 *                                     validation.
 	 */
-	public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userName, String password, DbType dbType, boolean sslEnabled, boolean sslVerify) {
+	public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userName, String password, DbType dbType, boolean sslEnabled, boolean sslVerify, String customSslValidationClassName) {
 		this.hostNameOrIP = hostNameOrIP;
 		this.portNumber = portNumber;
 		this.userName = userName;
@@ -92,6 +97,7 @@ public CaseDbConnectionInfo(String hostNameOrIP, String portNumber, String userN
 			throw new IllegalArgumentException("SQLite database type invalid for CaseDbConnectionInfo. CaseDbConnectionInfo should be used only for remote database types.");
 		}
 		this.dbType = dbType;
+		this.customSslValidationClassName = customSslValidationClassName;
 	}
 	
 	public DbType getDbType() {
@@ -149,4 +155,12 @@ public boolean isSslVerify() {
 	public void setSslVerify(boolean sslVerify) {
 		this.sslVerify = sslVerify;
 	}	
+
+	public String getCustomSslValidationClassName() {
+		return customSslValidationClassName;
+	}
+
+	public void setCustomSslValidationClassName(String customSslValidationClassName) {
+		this.customSslValidationClassName = customSslValidationClassName;
+	}
 }
diff --git a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
index e2047be0a7b47e3a8de078cc401ef28d6b4bedab..6eceb161aae93bf8d6e8561849375ba300c3396f 100644
--- a/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
+++ b/bindings/java/src/org/sleuthkit/datamodel/SleuthkitCase.java
@@ -1,7 +1,7 @@
 /*
  * Sleuth Kit Data Model
  *
- * Copyright 2011-2021 Basis Technology Corp.
+ * Copyright 2011-2023 Basis Technology Corp.
  * Contact: carrier <at> sleuthkit <dot> org
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -296,7 +296,12 @@ public static void tryConnect(CaseDbConnectionInfo info) throws TskCoreException
 			String connectionURL = "jdbc:postgresql://" + info.getHost() + ":" + info.getPort() + "/postgres";
 			if (info.isSslEnabled()) {				
 				if (info.isSslVerify()) {
-					connectionURL += CaseDatabaseFactory.SSL_VERIFY_URL;
+					if (info.getCustomSslValidationClassName().isBlank()) {
+						connectionURL += CaseDatabaseFactory.SSL_VERIFY_DEFAULT_URL;
+					} else {
+						// use custom SSL certificate validation class
+						connectionURL += CaseDatabaseFactory.getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName());
+					}
 				} else {
 					connectionURL += CaseDatabaseFactory.SSL_NONVERIFY_URL;
 				}
@@ -13407,7 +13412,12 @@ private final class PostgreSQLConnections extends ConnectionPool {
 					+ URLEncoder.encode(dbName, StandardCharsets.UTF_8.toString());
 			if (info.isSslEnabled()) {
 				if (info.isSslVerify()) {
-					connectionURL += CaseDatabaseFactory.SSL_VERIFY_URL;
+					if (info.getCustomSslValidationClassName().isBlank()) {
+						connectionURL += CaseDatabaseFactory.SSL_VERIFY_DEFAULT_URL;
+					} else {
+						// use custom SSL certificate validation class
+						connectionURL += CaseDatabaseFactory.getCustomPostrgesSslVerificationUrl(info.getCustomSslValidationClassName());
+					}
 				} else {
 					connectionURL += CaseDatabaseFactory.SSL_NONVERIFY_URL;
 				}