snowflakedb/snowflake-jdbc

SNOW-1272895: Key Pair Authentication with Encrypted Key Not Working

Closed this issue · 9 comments

  1. What version of JDBC driver are you using?
    3.15.0

  2. What operating system and processor architecture are you using?
    Macbook M1 Max, Sonoma 14.4.1

  3. What version of Java are you using?
    openjdk version "1.8.0_402"
    OpenJDK Runtime Environment (Temurin)(build 1.8.0_402-b06)
    OpenJDK 64-Bit Server VM (Temurin)(build 25.402-b06, mixed mode)

  4. What did you do?

I'm unable to create a connection using the JDBC driver when using Key Pair authentication with an encrypted key. This works fine when using an unencrypted key, but that is not sufficient for our security needs.

To generate the key, I used the default instructions found at https://docs.snowflake.com/en/user-guide/key-pair-auth and am using openssl v3.1.1. I am also running the basic test program provided at https://docs.snowflake.com/en/developer-guide/jdbc/jdbc-using#java-sample-program.

openssl genrsa 2048 | openssl pkcs8 -topk8 -v2 des3 -inform PEM -out rsa_key.p8
openssl rsa -in rsa_key.p8 -pubout -out rsa_key.pub

I was able to connect to the Snowflake account using these credentials with SnowSQL. The script for that is below for reference.

export SNOWSQL_PRIVATE_KEY_PASSPHRASE="password"
snowsql -a "xxxxxxx" -u test_user -d core_test_db -r core_test_role -w core_test_wh --private-key-path "/Users/xxxxxx/testing/rsa_key.p8" -q "select CURRENT_CLIENT();"

However, when I attempt to do so with the JDBC driver in a test program, I receive the error below.

Exception in thread "main" net.snowflake.client.jdbc.SnowflakeSQLLoggedException: Private key provided is invalid or not supported: /Users/xxxxxxx/testing/rsa_key.p8: PBE parameter parsing error: expecting the object identifier for AES cipher
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initialize(DefaultSFConnectionHandler.java:130)
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initializeConnection(DefaultSFConnectionHandler.java:98)
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.initConnectionWithImpl(SnowflakeConnectionV1.java:140)
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.<init>(SnowflakeConnectionV1.java:120)
        at net.snowflake.client.jdbc.SnowflakeDriver.connect(SnowflakeDriver.java:211)
        at java.sql.DriverManager.getConnection(DriverManager.java:664)
        at java.sql.DriverManager.getConnection(DriverManager.java:208)
        at SnowflakeJDBCExample.getConnection(SnowflakeJDBCExample.java:91)
        at SnowflakeJDBCExample.main(SnowflakeJDBCExample.java:31)
  1. What did you expect to see?

I expected the JDBC driver to connect without issue.

  1. Can you set logging to DEBUG and collect the logs?

Here are the full logs...

Create JDBC connection
Exception in thread "main" net.snowflake.client.jdbc.SnowflakeSQLLoggedException: Private key provided is invalid or not supported: /Users/xxxxxx/testing/rsa_key.p8: PBE parameter parsing error: expecting the object identifier for AES cipher
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initialize(DefaultSFConnectionHandler.java:130)
        at net.snowflake.client.jdbc.DefaultSFConnectionHandler.initializeConnection(DefaultSFConnectionHandler.java:98)
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.initConnectionWithImpl(SnowflakeConnectionV1.java:140)
        at net.snowflake.client.jdbc.SnowflakeConnectionV1.<init>(SnowflakeConnectionV1.java:120)
        at net.snowflake.client.jdbc.SnowflakeDriver.connect(SnowflakeDriver.java:211)
        at java.sql.DriverManager.getConnection(DriverManager.java:664)
        at java.sql.DriverManager.getConnection(DriverManager.java:208)
        at SnowflakeJDBCExample.getConnection(SnowflakeJDBCExample.java:93)
        at SnowflakeJDBCExample.main(SnowflakeJDBCExample.java:31)

Hello @KevinMellott91 ,

Thanks for raising the issue, will look into it.
Did you face the issue recently with 3.15.0 or it never worked before? was it working before or this is first time you trying with encrypted keys? Was it working with any previous version of openSSL before v3.1.1.

Regards,
Sujan

This issue is applicable to 3.15.0 too.

Hello @KevinMellott91 ,

Thanks for raising the issue, will look into it. Did you face the issue recently with 3.15.0 or it never worked before? was it working before or this is first time you trying with encrypted keys? Was it working with any previous version of openSSL before v3.1.1.

Regards, Sujan

I haven't gotten this working before (never tried in the past), but I was not able to get the 3.13.30 driver to work either.

For context, I was trying driver 3.13.30 first because that is the version used within my Flyway version. When the Flyway connection could not be made, I dug deeper into the driver itself to find this issue.

Hello @KevinMellott91 ,

This is a commonly known issue with Java not supporting most modern encrypted key types
https://github.com/snowflakedb/snowflake-sdks-drivers-issues-teamwork/issues/618

As a workaround you can try the below command
openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -v1 PBE-SHA1-RC4-128 -out rsa_key.p8

if it doesnt work, please generate and export it from the older OpenSSL version, its still a secure private key of the legacy format.

Regards,
Sujan

Hello @KevinMellott91 ,

This is a commonly known issue with Java not supporting most modern encrypted key types https://github.com/snowflakedb/snowflake-sdks-drivers-issues-teamwork/issues/618

As a workaround you can try the below command openssl genrsa 2048 | openssl pkcs8 -topk8 -inform PEM -v1 PBE-SHA1-RC4-128 -out rsa_key.p8

if it doesnt work, please generate and export it from the older OpenSSL version, its still a secure private key of the legacy format.

Regards, Sujan

Hi @sfc-gh-sghosh thanks for the workaround information. Unfortunately, I won't be able to use this due to security team requirements.

However, I was wondering if #1671 is a fix for this issue? If I'm understanding the update correctly, it appears it would add a configuration that would allow Bouncy Castle to handle the decryption aspects.

Hi @KevinMellott91,

Yes, that's the objective of PR #1671. Would it be possible for you to build that PR and test the fix?
Once you build the JDBC driver and replace your JAR, add the JVM argument
-Dnet.snowflake.jdbc.enableBouncyCastle=true

@sfc-gh-wfateem I just tested with a local version of the driver (built from that PR branch), and all worked as expected! That PR will fix this issue.

PR #1671 has been merged and we'll add documentation concerning the new JVM argument.