2

While configuring a tomcat with a jndi datasource to connect using ssl authentication to a postgres server (see providing certificates to tomcat jndi connection to postgresql) I have the following error:

[main] WARN org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator - HHH000342: Could not obtain connection to query metadata : Cannot create PoolableConnectionFactory (Could not find a java cryptographic algorithm: Cannot find any provider supporting 1.2.840.113549.1.5.13.)

(this is a warning in initialization time, but when I actually try to use the connection, I see the same as an error preventing to access the database).

Based on this answer: Reading PKCS8 in PEM format: Cannot find provider I have tried to modify /usr/lib/jvm/java-11-openjdk-amd64/conf/security/java.security by adding org.bouncycastle.jce.provider.BouncyCastleProvider as the first security provider. I also tried to add the jar bcprov-jdk15on-1.64.jar to /usr/lib/jvm/java-11-openjdk-amd64/lib and /usr/share/java (there was no lib/ext directory anywhere).

The problem still persists.

How should I tell to use the Bouncy Castle security provider either to the java runtime or tomcat or hibernate?

Update: Also tried to install libbcprov-java and set the security provider in java.security, but no success.

Árpád Magosányi
  • 1,394
  • 2
  • 19
  • 35
  • That exception message doesn't say what object (API) it wants. As I said in the A you link, that OID is the 'outer' (generic) OID for PBES2. It is not an actual scheme and is not implemented as a scheme by the standard providers _or_ Bouncy, but standard SunJCE (_not_ Bouncy) does implement it (as an alias for `PBES2`) for `AlgorithmParameters` (to parameterize the actual schemes). Did or can you get a full stacktrace, or at least the top 10 or so? If it's swallowed by hibernate, try a standalone program that just connects with same driver and connstring. ... – dave_thompson_085 Oct 21 '19 at 17:17
  • ... Or as a workaround you might change the key to a single-level scheme; the original PKCS5v1 schemes are all broken, but the PKCS12 scheme pbeWithSHA1And3-KeyTripleDES-CBC is still acceptable and even fairly common. Finally, yes, lib/ext was removed as of java 9; now you either put an add-on like bcprov in classpath, or if you really want it in the JRE use jlink to create a 'tailored' JRE. – dave_thompson_085 Oct 21 '19 at 17:21
  • You can find a full stacktrace here: https://github.com/pgjdbc/pgjdbc/issues/1585 As I understand SunJCE does implement it, but does not know the oid, while Bouncy implements it. If I could understand how to modify the key, I would. I have already converted it to pkcs-8, but it did not help. – Árpád Magosányi Oct 21 '19 at 19:15

1 Answers1

5

I think that's enough info for answer, which is more readable than comments. And safer.

Both SunJCE and bcprov implement Cipher instances for several PBES2-family ciphers (and PBKDF2 as a component) but neither implements a Cipher for PBES2 as such, either by name or OID, because PBES2 is not one cipher, it is a (large) family of them. As I noted, SunJCE does implement AlgorithmParameters for PBES2 by both OID and name. (Bouncy of course implements PBES2 parameters internally, and it looks to me like they are usable in the direct or 'lightweight' API, but it does not expose them through the provider SPI.)

Your keyfile is in PKCS8 encrypted format; the issue is that PKCS8 encryption can use many encryption schemes (ciphers), including the PBES2 family which is not identified by one OID (like the older/simpler ones from PKCS5v1 and PKCS12) but three: 'outer' PBES2, PBKDF2 (with derivation params), and the underlying symmetric cipher (with encryption params).

Assuming https://github.com/pgjdbc/pgjdbc/blob/master/pgjdbc/src/main/java/org/postgresql/ssl/LazyKeyManager.java is the correct code (line number 205 does match your stacktrace), that obviously isn't designed to handle the two-level (PBES2) case. However, it does try unencrypted PKCS8 first, and only if that fails tries encrypted PKCS8 with a scheme identified by one OID. Thus if having an unencrypted keyfile in your environment is acceptable, that should work, and so should my suggestion of using PKCS8 encrypted with a single-level scheme like PKCS12's pbeWithSHAAnd3-KeyTripleDES-CBC -- which on checking I see SunJCE actually names PBEWithSHA1AndDESede but uses the correct OID 1.2.840.113549.1.12.1.3 which is all that matters here. (bcprov uses the standard name except in uppercase -- JCA is case-insensitive.)

Depending on what software or process is creating your keyfile, it may be possible to adjust that to produce the desired format. If not, and you have or get OpenSSL, it can handle many (most) PKCS8 options:

# we need an intermediate PEM file; for safety (PB)encrypt it
openssl pkey <p8unusable.der -inform d -aes256 >temp.pem

# to unencrypted PKCS8
openssl pkcs8 -topk8 <temp.pem -outform d -nocrypt >p8unenc.der

# to encrypted PKCS8 using single-level PKCS12 scheme
openssl pkcs8 -topk8 <temp.pem -outform d -v1 pbeWithSHA1And3-KeyTripleDES-CBC >p8encone.der
# note OpenSSL spells SHA1 where PKCS12 had SHA (which was technically wrong)
# OTOH OpenSSL implies this is PKCS5v1 which it isn't. Bleah.

rm temp.pem # or erase or whatever
Community
  • 1
  • 1
dave_thompson_085
  • 34,712
  • 6
  • 50
  • 70
  • The solution was to give -v1 PBE-MD5-DES option to openssl pkcs8. As I see your solution is basically the same but more researched. So I accept t. – Árpád Magosányi Oct 24 '19 at 17:39
  • 1
    The disadvantage of PBE-MD5-DES is that single-DES has been breakable for 20 years, and today very easily -- last I looked it cost about $50 -- so it isn't actually secure, but someone who just glances at it and sees it's encrypted might think it is. – dave_thompson_085 Oct 26 '19 at 03:46