diff --git a/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java b/bindings/java/src/org/sleuthkit/datamodel/CaseDatabaseFactory.java
index 8eb7eee9f4cb23f8a66b26063c99d6128fdd41e4..782c1ffe86ba0bf6fb00ebe5feb0c77eb3094259 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 application's default JRE keystore 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..3fc1af058c216ac4179acd9ce2e8cb8b09527a17 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,13 +63,20 @@ 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 = "";
 	}
 	 
 	/**
 	 * The intent of this class is to hold any information needed to connect to
-	 * a remote database server, except for the actual database name. This constructor 
-	 * allows user to specify whether to use SSL to connect to database. This does
-	 * not hold information to connect to a local database such as SQLite.
+	 * a remote database server, except for the actual database name. This
+	 * constructor allows user to specify whether to use SSL to connect to
+	 * database. This does not hold information to connect to a local database
+	 * such as SQLite.
+	 *
+	 * This constructor allows to specify a Java class that performs custom
+	 * PostgreQSL server SSL certificate validation (if 'sslVerify' is set to
+	 * 'true'). If not specified, the application's default JRE keystore will be
+	 * used.
 	 *
 	 * It can be used generically to hold remote database connection
 	 * information.
@@ -80,8 +88,14 @@ 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. If blank, the
+	 *                                     application's default JRE keystore
+	 *                                     will be used.
 	 */
-	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 +106,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 +164,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..0ecdf3e75db59a6a10644b4b3a97229f62a6c91e 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");
@@ -113,8 +113,8 @@ public class SleuthkitCase {
 	private static final int IS_REACHABLE_TIMEOUT_MS = 1000;
 	private static final String SQL_ERROR_CONNECTION_GROUP = "08";
     // either one of these mean connection was rejected by Postgres server
-    private static final String SQL_CONNECTION_REJECTED_1 = "08004";
-    private static final String SQL_CONNECTION_REJECTED_2 = "08006";
+    private static final String SQL_CONNECTION_REJECTED = "08004";
+    private static final String UNABLE_TO_VERIFY_SSL = "08006";
 	
 	private static final String SQL_ERROR_AUTHENTICATION_GROUP = "28";
 	private static final String SQL_ERROR_PRIVILEGE_GROUP = "42";
@@ -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;
 				}
@@ -308,15 +313,15 @@ public static void tryConnect(CaseDbConnectionInfo info) throws TskCoreException
 		} catch (SQLException ex) {
 			String result;
 			String sqlState = ex.getSQLState().toLowerCase();
-			if (sqlState.startsWith(SQL_ERROR_CONNECTION_GROUP)) {
-				
-				if (SQL_CONNECTION_REJECTED_1.equals(ex.getSQLState()) ||
-						SQL_CONNECTION_REJECTED_2.equals(ex.getSQLState())) {
+			if (sqlState.startsWith(SQL_ERROR_CONNECTION_GROUP)) {				
+				if (SQL_CONNECTION_REJECTED.equals(ex.getSQLState())) {
 					if (info.isSslEnabled()) {
 						result = "Server rejected the SSL connection attempt. Check SSL configuration.";
 					} else {
 						result = "Server rejected the connection attempt. Check server configuration.";
 					}					
+				} else if (UNABLE_TO_VERIFY_SSL.equals(ex.getSQLState())) {
+					result = "Unable to verify SSL certificates. Check SSL configuration.";
 				} else {
 					try {
 						if (InetAddress.getByName(info.getHost()).isReachable(IS_REACHABLE_TIMEOUT_MS)) {
@@ -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;
 				}