No More Java DB Password in The Clear
As I mentioned in my previous blog, Java DB's legacy is in the embedded world, where there is no such thing as sending the password over the wire.
But when you introduce the network client, this becomes an issue. And sending users and passwords in the clear is just not acceptable. So this blog tells you how to stop that from happening.
- CLEAR_TEXT_PASSWORD_SECURITY (0x03) - User and password are sent in the clear. This is the default
- USER_ONLY_SECURITY (0x04) - Only the user is sent. This doesn't work if authentication is enabled on the server
- STRONG_PASSWORD_SUBSTITUTE_SECURITY (0x08) - "When using this mechanism, a strong password substitute is generated and used to authenticate the user with the network server. The original password is never sent in any form across the network." (from the docs)
- ENCRYPTED_USER_AND_PASSWORD_SECURITY (0x09) - The user and password are encrypted using a pluggable encryption mechanism
Now, why on earth am I including the hex value for the security mechanism here? Because (and I kid you not), when you specify the security mechanism you want to use on your URL, you have to pass the numeric value for the mechanism, not the name.
Needless to say, when I discovered this, I immediately logged a bug. It didn't help that nowhere do the docs actually tell you you need to do this. I had to figure this out through a series of experiments and failures.
And get this, you have to convert the hex value to an integer, if you pass in 0x08 you get a NumberFormatException. Sweet.
Anyway, I'm here to help. If you want security, you probably want to choose STRONG_PASSWORD_SUBSTITUTE or ENCRYPTED_USER_AND_PASSWORD. I personally don't know the difference in terms of strength/breakability, but I do know that if you choose ENCRYPTED_USER_AND_PASSWORD, then you also need to install IBM JCE and configure the JRE to use an appropriate security provider. You have to do this for the JRE used by both the client and the server. If you are deploying your client to a wide swath of machines, this particular approach is not feasible, as far as I can tell. I am pinging the Derby user group about this, more info will be posted here if I get it.
So, personally, I'm opting for STRONG_PASSWORD_SUBSTITUTE (or 8 if you're thinking in integers). Here's how you do it:
First, if you want to enforce that only this security mechanism be used, you can configure the network server by putting this line in derby.properties:
Next, when you connect, include the securityMechanism property in your URL, e.g
Now your password is no longer flying over the wire in the clear.
UPDATE: After some discussion on the derby-user list, I have some more clarity about securing your network pipe.
First of all, the reason you can't use Sun's Java runtime to do password encryption with Java DB is because Java DB network communication uses DRDA, a standard network protocol (used primarily by IBM). DRDA's encryption protocol uses a 256-bit key, which is considered too short (and thus too weak) by Sun's encryption engine. IBM JCE does support a 256-bit key, so that's why you would need to install it. I have asked if there other encryption engines that support a 256-bit key.
The STRONG_PASSWORD_SUBSTITUTE mechanism I describe above was implemented as an alternative because standard encryption has these issues with support and configuration overhead.
There was also general agreement on the list that what you really want is encryption using industry-standard SSL (or its new incarnation, TLS). Java DB 10.3, which is getting ready to be released, will include support for SSL/TLS. Using this mechanism is recommended unless you are concerned about the performance impact of encrypting all communications and you are fine with just protecting the password.