Thread: JDBC with SSL

JDBC with SSL

From
Walter Hurry
Date:
First of all, I am sorry if this is the wrong place to ask. If it is,
perhaps someone could direct me to the right arena.

This is PostgreSQL 9.0.1 with PostgreSQL JDBC 9.1.901.

I have successfully set up one of my databases to require SSL connections
with a certificate, and installed a certificate into $HOME/.postgresql.
That directory contains postgresql.crt,  postgresql.key and root.crt.

I can connect successfully using psql and libpq applications. The
connection is also rejected properly if I move the certificate out of the
way.

Now I am trying to connect using JDBC and SSL from a Java application
(JDBC is fine without SSL on another database). However, I am getting the
following error:

FATAL: connection requires a valid client certificate

So it appears that somehow I need to "tell" Java where to find the client
certificate. Any pointers as to how I do this please?

By the way, since this is a self-signed certificate I have followed the
instructions at <http://jdbc.postgresql.org/documentation/81/ssl-
client.html>. These succeeded, but I am still getting the error.

Thanks,
Walter




Re: JDBC with SSL

From
Florent Guillaume
Date:
Hi,

You have to install the certificate in the Java keystore using "keytool".
See http://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html
for a quick overview.
A more detailed doc is at
http://docs.oracle.com/javaee/1.4/tutorial/doc/Security6.html

Florent

On Sun, Dec 4, 2011 at 5:40 PM, Walter Hurry <walterhurry@lavabit.com> wrote:
> First of all, I am sorry if this is the wrong place to ask. If it is,
> perhaps someone could direct me to the right arena.
>
> This is PostgreSQL 9.0.1 with PostgreSQL JDBC 9.1.901.
>
> I have successfully set up one of my databases to require SSL connections
> with a certificate, and installed a certificate into $HOME/.postgresql.
> That directory contains postgresql.crt,  postgresql.key and root.crt.
>
> I can connect successfully using psql and libpq applications. The
> connection is also rejected properly if I move the certificate out of the
> way.
>
> Now I am trying to connect using JDBC and SSL from a Java application
> (JDBC is fine without SSL on another database). However, I am getting the
> following error:
>
> FATAL: connection requires a valid client certificate
>
> So it appears that somehow I need to "tell" Java where to find the client
> certificate. Any pointers as to how I do this please?
>
> By the way, since this is a self-signed certificate I have followed the
> instructions at <http://jdbc.postgresql.org/documentation/81/ssl-
> client.html>. These succeeded, but I am still getting the error.
>
> Thanks,
> Walter
>
>
>
>
>
> --
> Sent via pgsql-jdbc mailing list (pgsql-jdbc@postgresql.org)
> To make changes to your subscription:
> http://www.postgresql.org/mailpref/pgsql-jdbc
>



--
Florent Guillaume, Director of R&D, Nuxeo
Open Source, Java EE based, Enterprise Content Management (ECM)
http://www.nuxeo.com   http://www.nuxeo.org   +33 1 40 33 79 87

Re: JDBC with SSL

From
Walter Hurry
Date:
On Sun, 04 Dec 2011 20:09:09 +0100, Florent Guillaume wrote:

> Hi,
>
> You have to install the certificate in the Java keystore using
> "keytool". See
> http://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html for
> a quick overview.
> A more detailed doc is at
> http://docs.oracle.com/javaee/1.4/tutorial/doc/Security6.html
>
> Florent
>
> On Sun, Dec 4, 2011 at 5:40 PM, Walter Hurry <walterhurry@lavabit.com>
> wrote:
>> First of all, I am sorry if this is the wrong place to ask. If it is,
>> perhaps someone could direct me to the right arena.
>>
>> This is PostgreSQL 9.0.1 with PostgreSQL JDBC 9.1.901.
>>
>> I have successfully set up one of my databases to require SSL
>> connections with a certificate, and installed a certificate into
>> $HOME/.postgresql. That directory contains postgresql.crt,
>>  postgresql.key and root.crt.
>>
>> I can connect successfully using psql and libpq applications. The
>> connection is also rejected properly if I move the certificate out of
>> the way.
>>
>> Now I am trying to connect using JDBC and SSL from a Java application
>> (JDBC is fine without SSL on another database). However, I am getting
>> the following error:
>>
>> FATAL: connection requires a valid client certificate
>>
>> So it appears that somehow I need to "tell" Java where to find the
>> client certificate. Any pointers as to how I do this please?
>>
>> By the way, since this is a self-signed certificate I have followed the
>> instructions at <http://jdbc.postgresql.org/documentation/81/ssl-
>> client.html>. These succeeded, but I am still getting the error.
>>
>> Thanks,
>> Walter

Thanks for the reply, Florent. I have followed the instructions yu
mentioned carefully, and am now invoking the class with:

java -Djava.security.manager -Djava.security.policy=clientpolicy
<classname>

but I am getting:

Your security policy has prevented the connection from being attempted.
You probably need to grant the connect java.net.SocketPermission to the
database server host and port that you wish to connect to.

Where do I go from here?

Thanks again,
Walter

Re: JDBC with SSL

From
Craig Ringer
Date:
On 12/05/2011 04:48 AM, Walter Hurry wrote:
> On Sun, 04 Dec 2011 20:09:09 +0100, Florent Guillaume wrote:
>
>> Hi,
>>
>> You have to install the certificate in the Java keystore using
>> "keytool". See
>> http://docs.oracle.com/javase/tutorial/security/toolsign/rstep2.html for
>> a quick overview.
>> A more detailed doc is at
>> http://docs.oracle.com/javaee/1.4/tutorial/doc/Security6.html
>>
>> Florent
>>
>> On Sun, Dec 4, 2011 at 5:40 PM, Walter Hurry<walterhurry@lavabit.com>
>> wrote:
>>> First of all, I am sorry if this is the wrong place to ask. If it is,
>>> perhaps someone could direct me to the right arena.
>>>
>>> This is PostgreSQL 9.0.1 with PostgreSQL JDBC 9.1.901.
>>>
>>> I have successfully set up one of my databases to require SSL
>>> connections with a certificate, and installed a certificate into
>>> $HOME/.postgresql. That directory contains postgresql.crt,
>>>   postgresql.key and root.crt.
>>>
>>> I can connect successfully using psql and libpq applications. The
>>> connection is also rejected properly if I move the certificate out of
>>> the way.
>>>
>>> Now I am trying to connect using JDBC and SSL from a Java application
>>> (JDBC is fine without SSL on another database). However, I am getting
>>> the following error:
>>>
>>> FATAL: connection requires a valid client certificate
>>>
>>> So it appears that somehow I need to "tell" Java where to find the
>>> client certificate. Any pointers as to how I do this please?
>>>
>>> By the way, since this is a self-signed certificate I have followed the
>>> instructions at<http://jdbc.postgresql.org/documentation/81/ssl-
>>> client.html>. These succeeded, but I am still getting the error.
>>>
>>> Thanks,
>>> Walter
> Thanks for the reply, Florent. I have followed the instructions yu
> mentioned carefully, and am now invoking the class with:
>
> java -Djava.security.manager -Djava.security.policy=clientpolicy
> <classname>
>
You don't need the SecurityManager enabled. You need the java.net.ssl
properties for keyStore, keyStorePassword and keyStoreType set to point
to your JECKS keystore, and need trustStore, trustStorePassword and
trustStoreType set to point to the keystore you imported the database's
certificate into, which is probably the same store in your case.

Alternately, you can use the custom certificate manager class posted on
this mailing list a while ago to manage key and trust store lookup from
your own stores at runtime.

--
Craig Ringer

Re: JDBC with SSL

From
Walter Hurry
Date:
On Mon, 05 Dec 2011 08:28:33 +0800, Craig Ringer wrote:

> You don't need the SecurityManager enabled. You need the java.net.ssl
> properties for keyStore, keyStorePassword and keyStoreType set to point
> to your JECKS keystore, and need trustStore, trustStorePassword and
> trustStoreType set to point to the keystore you imported the database's
> certificate into, which is probably the same store in your case.

<snip option 2>

Thanks for the guidance, Craig. I'm trying to use javax.net.ssl but I'm
still stuck. Sample below:
-------------------------------------------------------------
$ java -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
       -Djavax.net.ssl.keyStorePassword=changeit \
       -Djavax.net.ssl.keyStoreType="jks" \
       -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
       -Djavax.net.ssl.trustStorePassword=changeit \
       -Djavax.net.ssl.trustStoreType="jks" \
       JDBCExample neptune misc
-------- PostgreSQL JDBC Connection Testing ------------
PostgreSQL JDBC driver registered
Getting connection to jdbc:postgresql://neptune/misc
Connect failed: FATAL: connection requires a valid client certificate
-------------------------------------------------------------

Any idea what I am doing wrong?

Thanks.


Re: JDBC with SSL

From
Magosányi Árpád
Date:
Maybe a take in the wrong direction, but have you checked that all certs
are existing and valid throughout the certificate chain?
I am talking about both the server and the client side.
(Yes, you have already said that it does work with psql, so the question
is whether all certs and the key are imported correctly into the keystore.)

BTW I have found more convenient to use the same keystore for both the
client cert/key and the trust anchors.

On 12/05/2011 07:46 PM, Walter Hurry wrote:
> On Mon, 05 Dec 2011 08:28:33 +0800, Craig Ringer wrote:
>
>> You don't need the SecurityManager enabled. You need the java.net.ssl
>> properties for keyStore, keyStorePassword and keyStoreType set to point
>> to your JECKS keystore, and need trustStore, trustStorePassword and
>> trustStoreType set to point to the keystore you imported the database's
>> certificate into, which is probably the same store in your case.
>
> <snip option 2>
>
> Thanks for the guidance, Craig. I'm trying to use javax.net.ssl but I'm
> still stuck. Sample below:
> -------------------------------------------------------------
> $ java -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
>         -Djavax.net.ssl.keyStorePassword=changeit \
>         -Djavax.net.ssl.keyStoreType="jks" \
>         -Djavax.net.ssl.trustStore=$JAVA_HOME/lib/security/cacerts \
>         -Djavax.net.ssl.trustStorePassword=changeit \
>         -Djavax.net.ssl.trustStoreType="jks" \
>         JDBCExample neptune misc
> -------- PostgreSQL JDBC Connection Testing ------------
> PostgreSQL JDBC driver registered
> Getting connection to jdbc:postgresql://neptune/misc
> Connect failed: FATAL: connection requires a valid client certificate
> -------------------------------------------------------------
>
> Any idea what I am doing wrong?
>
> Thanks.
>
>
>


Re: JDBC with SSL

From
Craig Ringer
Date:
On 12/06/2011 02:46 AM, Walter Hurry wrote:
> -------------------------------------------------------------
> $ java -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
>         -Djavax.net.ssl.keyStorePassword=changeit \
>         -Djavax.net.ssl.keyStoreType="jks" \
>
I thought you could only use a JECKS store when including private keys?

--
Craig Ringer

Re: JDBC with SSL

From
Walter Hurry
Date:
On Tue, 06 Dec 2011 08:45:48 +0800, Craig Ringer wrote:

> On 12/06/2011 02:46 AM, Walter Hurry wrote:
>> ------------------------------------------------------------- $ java
>> -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
>>         -Djavax.net.ssl.keyStorePassword=changeit \
>>         -Djavax.net.ssl.keyStoreType="jks" \
>>
> I thought you could only use a JECKS store when including private keys?

Sorry, I'm pretty new to all this. What is a JECKS store? Does it mean I
have the keyStoreType wrong?


Re: JDBC with SSL

From
Craig Ringer
Date:
On 07/12/11 03:43, Walter Hurry wrote:
> On Tue, 06 Dec 2011 08:45:48 +0800, Craig Ringer wrote:
>
>> On 12/06/2011 02:46 AM, Walter Hurry wrote:
>>> ------------------------------------------------------------- $ java
>>> -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
>>>         -Djavax.net.ssl.keyStorePassword=changeit \
>>>         -Djavax.net.ssl.keyStoreType="jks" \
>>>
>> I thought you could only use a JECKS store when including private keys?
> Sorry, I'm pretty new to all this. What is a JECKS store? Does it mean I
> have the keyStoreType wrong?

JKS and JECKS are two different key store formats. Keytool understands
both. If my memory serves, JECKS is the encrypted keystore format,
intended for storing private key data. I think you can use JECKS for
both certificate and key data, but you can use JKS only for certificate
data, NOT  for key data.

If you want your trusted certs and your client certs+keys in the same
store, use a JECKS store by passing the "-storetype JECKS" argument to
keytool when creating the store and importing a cert into it. I have the
niggling memory that if you use the JKS store (default) then keytool
imports the certificate from your input pkcs#2 (or whatever) file and
ignores the key.

--
Craig Ringer

Re: JDBC with SSL

From
Bruno Harbulot
Date:
On 07/12/2011 05:06, Craig Ringer wrote:
> On 07/12/11 03:43, Walter Hurry wrote:
>> On Tue, 06 Dec 2011 08:45:48 +0800, Craig Ringer wrote:
>>
>>> On 12/06/2011 02:46 AM, Walter Hurry wrote:
>>>> ------------------------------------------------------------- $ java
>>>> -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
>>>>          -Djavax.net.ssl.keyStorePassword=changeit \
>>>>          -Djavax.net.ssl.keyStoreType="jks" \
>>>>
>>> I thought you could only use a JECKS store when including private keys?
>> Sorry, I'm pretty new to all this. What is a JECKS store? Does it mean I
>> have the keyStoreType wrong?
>
> JKS and JECKS are two different key store formats. Keytool understands
> both. If my memory serves, JECKS is the encrypted keystore format,
> intended for storing private key data. I think you can use JECKS for
> both certificate and key data, but you can use JKS only for certificate
> data, NOT  for key data.

You can store certificates and/or private keys in both JKS and JECKS.

PKCS12 is somewhat different in that, to store a certificate (or a
certificate chain), it requires there to be a private key associated
with this certificate. Java isn't the only implementation with this
limitation, but I must admit I can't remember what the PKCS#12
specification itself says about it.


More details on JKS/JECKS, from:
http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/CryptoSpec.html#KeystoreImplementation

> jceks" is an alternate proprietary keystore format to "jks" that uses much stronger encryption in the form of
Password-BasedEncryption with Triple-DES. 



The default keystore type with the Oracle security provider is JKS; you
can check this using KeyStore.getDefaultType().


If your initial key and certs where in PEM format (as used by psql), it
might be easier to build a PKCS#12 store with OpenSSL:

    openssl pkcs12 -export -in usercert.pem -inkey userkey.pem -out
usercreds.p12


You can then use it with KeyStore type "PKCS12" (no #) from Java directly.
You could also convert this PKCS#12 file into a JKS/JECKS keystore using
keytool and its -importstore options (only in Java 6+).


Best wishes,

Bruno.

Re: JDBC with SSL

From
Bruno Harbulot
Date:
On 07/12/2011 16:27, Bruno Harbulot wrote:
>
> You can then use it with KeyStore type "PKCS12" (no #) from Java directly.
> You could also convert this PKCS#12 file into a JKS/JECKS keystore using
> keytool and its -importstore options (only in Java 6+).
>

Sorry, I meant -importkeystore:

   keytool -importkeystore -srckeystore usercreds.p12 \
                           -srsstoretype PKCS12 \
                           -destkeystore usercreds.jceks \
                           -deststoretype JCEKS


Best wishes,

Bruno.

Re: JDBC with SSL

From
Walter Hurry
Date:
On Wed, 07 Dec 2011 16:27:47 +0000, Bruno Harbulot wrote:

> On 07/12/2011 05:06, Craig Ringer wrote:
>> On 07/12/11 03:43, Walter Hurry wrote:
>>> On Tue, 06 Dec 2011 08:45:48 +0800, Craig Ringer wrote:
>>>
>>>> On 12/06/2011 02:46 AM, Walter Hurry wrote:
>>>>> ------------------------------------------------------------- $ java
>>>>> -Djavax.net.ssl.keyStore=$HOME/.postgresql/clientstore \
>>>>>          -Djavax.net.ssl.keyStorePassword=changeit \
>>>>>          -Djavax.net.ssl.keyStoreType="jks" \
>>>>>
>>>> I thought you could only use a JECKS store when including private
>>>> keys?
>>> Sorry, I'm pretty new to all this. What is a JECKS store? Does it mean
>>> I have the keyStoreType wrong?
>>
>> JKS and JECKS are two different key store formats. Keytool understands
>> both. If my memory serves, JECKS is the encrypted keystore format,
>> intended for storing private key data. I think you can use JECKS for
>> both certificate and key data, but you can use JKS only for certificate
>> data, NOT  for key data.
>
> You can store certificates and/or private keys in both JKS and JECKS.
>
> PKCS12 is somewhat different in that, to store a certificate (or a
> certificate chain), it requires there to be a private key associated
> with this certificate. Java isn't the only implementation with this
> limitation, but I must admit I can't remember what the PKCS#12
> specification itself says about it.
>
>
> More details on JKS/JECKS, from:
> http://docs.oracle.com/javase/6/docs/technotes/guides/security/crypto/
CryptoSpec.html#KeystoreImplementation
>
>> jceks" is an alternate proprietary keystore format to "jks" that uses
>> much stronger encryption in the form of Password-Based Encryption with
>> Triple-DES.
>
>
>
> The default keystore type with the Oracle security provider is JKS; you
> can check this using KeyStore.getDefaultType().
>
>
> If your initial key and certs where in PEM format (as used by psql), it
> might be easier to build a PKCS#12 store with OpenSSL:
>
>     openssl pkcs12 -export -in usercert.pem -inkey userkey.pem -out
> usercreds.p12
>
>
> You can then use it with KeyStore type "PKCS12" (no #) from Java
> directly.
> You could also convert this PKCS#12 file into a JKS/JECKS keystore using
> keytool and its -importstore options (only in Java 6+).

Eureka! That nailed it (I used the pkcs12 file as it was, and didn't
bother to convert it). Very many thanks Bruno, and to everyone who
offered help. It is deeply appreciated.

$ java -Djavax.net.ssl.keyStore=$HOME/.postgresql/postgresql.p12 \
>        -Djavax.net.ssl.keyStorePassword=changeit \
>        -Djavax.net.ssl.keyStoreType=PKCS12 \
>        -Djavax.net.ssl.trustStore=$HOME/.postgresql/server.jceks \
>        -Djavax.net.ssl.trustStorePassword=changeit \
>        -Djavax.net.ssl.trustStoreType=jceks \
>        JDBCExample neptune misc
-------- PostgreSQL JDBC Connection Testing ------------
PostgreSQL JDBC driver registered
Getting connection to jdbc:postgresql://neptune/misc
Connection successful
$

Thanks again,
Walter