Thread: JDBC with SSL
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
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
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
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
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.
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. > > >
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
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?
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
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.
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.
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