bcgit / bc-java

Bouncy Castle Java Distribution (Mirror)
https://www.bouncycastle.org/java.html
MIT License
2.33k stars 1.14k forks source link

Java 5 TLS 1.2 for jdbc connection #1899

Open abhissha opened 2 weeks ago

abhissha commented 2 weeks ago

I am trying to use Bouncy castle in Java 5 to support TLS 1.2 for JDBC connection. Based on the documentation, I can't figure out how to achieve this, since examples seems to be for Java 8 and above. Are there any working examples or documentation that I can follow to achieve my goal?

peterdettman commented 2 weeks ago

You can use the "BCJSSE" provider (org.bouncycastle.jsse.provider.BouncyCastleJsseProvider) in Java 5. Most JSSE features that were added in later APIs can also be accessed via BCJSSE-specific extensions.

Refer to the BCJSSE tests for examples of usage; I think there is very little dependency on Java version in those tests.

abhissha commented 2 days ago

Based on the test cases, I tried below code and below is not working. Any help to direct in right direction would be appreciated.

I am trying to get this working on SQL JDBC driver and Java 5 based application.

The error I am getting is below: ov 19, 2024 1:23:02 PM org.bouncycastle.jsse.provider.PropertyUtils getStringSecurityProperty WARNING: String security property [jdk.tls.disabledAlgorithms] defaulted to: SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, ECDH Nov 19, 2024 1:23:02 PM org.bouncycastle.jsse.provider.PropertyUtils getStringSecurityProperty WARNING: String security property [jdk.certpath.disabledAlgorithms] defaulted to: MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224, SHA1 usage SignedJAR & denyAfter 2019-01-01 Nov 19, 2024 1:23:02 PM org.bouncycastle.jsse.provider.DisabledAlgorithmConstraints create WARNING: Ignoring unsupported entry in 'jdk.certpath.disabledAlgorithms': SHA1 jdkCA & usage TLSServer Nov 19, 2024 1:23:02 PM org.bouncycastle.jsse.provider.DisabledAlgorithmConstraints create WARNING: Ignoring unsupported entry in 'jdk.certpath.disabledAlgorithms': SHA1 usage SignedJAR & denyAfter 2019-01-01 Nov 19, 2024 1:23:02 PM org.bouncycastle.jsse.provider.PropertyUtils getStringSystemProperty INFO: Found string system property [java.home]: C:\data\myinstalls\java\jdk-1.5.0_22\jre Nov 19, 2024 1:23:02 PM org.bouncycastle.jsse.provider.PropertyUtils getStringSystemProperty INFO: Found string system property [java.home]: C:\data\myinstalls\java\jdk-1.5.0_22\jre

com.microsoft.sqlserver.jdbc.SQLServerException: The driver could not establish a secure connection to SQL Server by using Secure Sockets Layer (SSL) encryption. Error: "unable to create JcaTlsCrypto: DEFAULT SecureRandom not available".

I tried couple of different ways: dbConnectionString is just a connection string to database.

  1. Without making any code changes, added BouncyCastleJsseProvider as a default Provider ``` @Test public void testDBServerWithTLSv12AsOnlyOptionUsingBouncyCastleJsseProviderDirectly() throws Exception { BouncyCastleJsseProvider provider = new BouncyCastleJsseProvider(); Security.insertProviderAt(provider,1); // Connect to the database executeSQL(dbConnectionString); }
  2. Initializing TLSv1.2 as SSL Context. Based on https://docs.oracle.com/en/java/javase/15/security/transport-layer-security-tls-protocol-overview.html#GUID-D04EF7C1-B1D4-4611-9896-A7B5573CBEED, oracle talks about TLS V1.2 works without any cert/keyexchange, so set the keymanager/trustmanager to null. I also tried below with secureRandom as null with same issue.
    @Test
    public void testDBServerWithTLSv12AsOnlyOptionUsingBouncyCastleJsseProviderAndSSLContextWithDefaultSecureRandom() throws Exception {
        BouncyCastleJsseProvider provider = new BouncyCastleJsseProvider();
        Security.insertProviderAt(provider,1);
        SSLContext context = SSLContext.getInstance("TLSv1.2", provider.getName());
        SecureRandom secureRandom = new SecureRandom();
        CryptoServicesRegistrar.setSecureRandom(secureRandom);
        context.init(null,null, secureRandom);
        // Connect to the database
        executeSQL(dbConnectionString);
    }

executeSQL is pretty straight forward method, that just calls db with a select statement

private static void executeSQL(String connectionUrl) throws Exception {
        try {
            Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
            Connection connection = DriverManager.getConnection(connectionUrl);
            Statement statement = connection.createStatement();

            // Execute a SELECT SQL statement
            String selectSql = "SELECT Id=1";
            ResultSet resultSet = statement.executeQuery(selectSql);

            // Print results from the SELECT statement
            while (resultSet.next()) {
                System.out.println(resultSet.getString("Id"));
            }
        }
        catch(Exception e) {
            throw e;
        }
    }
peterdettman commented 2 days ago

I guess there is some issue trying to create a SecureRandom of type "DEFAULT" (the exception comes from here). I guess you are not using the BouncyCastle crypto provider ("BC") i.e. BouncyCastleProvider, which should have "DEFAULT".

You could create your own subclass of JcaTlsCryptoProvider so that you can override the create(SecureRandom) method (e.g. replace SecureRandom.getInstance("DEFAULT", ...) with new SecureRandom().

Then use the BouncyCastleJsseProvider(boolean, JcaTlsCryptoProvider) constructor to create the provider instance, passing your custom JcaTlsCryptoProvider subclass.