This library provides a drop in replacement for the standard Tomcat DataSourceFactory that allows the database connection password to be encrypted using a symmetric key for the purposes of security. This datasource uses the standard Cipher class from Java Cryptography Architecture to perform the decryption. As such all the algorithms installed in the JVM are available to use. By default, all JVM vendors must support the standard algorithms. Consult your vendor's documentation for any further algorithm support.
This library may also be run from the command line to generate an encryption key and encrypted password to be used in the Tomcat configuration.
The library can be tested using the docker compose.yml which starts a Tomcat service and a database. The following databases have been tested:
- Postgres 18
- MS SQL Server 2022
- Oracle 19c
- Download the latest version of the library from GitHub packages: https://github.com/orgs/lat-lon/packages?repo_name=secure-tomcat-datasourcefactory.
- You may download additional files to run the library standalone from the command line or within Tomcat. To download the correct dependencies run the Maven plugin:
mvn dependency:copy-dependencies -DincludeScope=compile -DoutputDirectory=./target. Copy the required filesjakarta.activation-api-X.Y.jarandjakarta.xml.bind-api-X.Y.jarto the Tomcat serverlib/folder.
- Generate a new random encryption key to a file e.g. to create a new 128-bit AES key run the command:
$ java -jar secure-tomcat-datasourcefactory-0.6.jar generateKey AES 128 /some/super/secure/location/keyfile
New key written to file: /some/super/secure/location/keyfile
-
The encryption key is now in the specified file e.g.
/some/super/secure/location/keyfile -
Generate the encrypted password in Base64 encoding e.g. using AES/ECB/PKCS5PADDING
$ java -jar secure-tomcat-datasourcefactory-0.6.jar encryptPassword mypassword AES ECB PKCS5PADDING /some/super/secure/location/keyfile
Encrypted password: O+JXajIzZS5Hi2+3vpdeqw==
-
Copy the JAR file to the folder
${TOMCAT_HOME}/lib -
Make the following changes to your JNDI datasource in
${TOMCAT_HOME}/conf/context.xml-
Add
factory="com.github.ncredinburgh.tomcat.SecureDataSourceFactory" -
Replace existing clear text
passwordvalue with Base64 encoded encrypted password e.g.password="O+JXajIzZS5Hi2+3vpdeqw==" -
Add algorithm details to
connectionPropertiese.g.algorithm=AES;mode=ECB;padding=PKCS5PADDING -
Add location of keyfile to
connectionPropertiese.g.keyFilename=/some/super/secure/location/keyfile
-
-
Congratulations you are done!
These examples are based on the examples given in Tomcat JNDI Datasource HOW-TO
<Resource name="jdbc/myoracle" auth="Container"
factory="com.github.ncredinburgh.tomcat.SecureDataSourceFactory"
type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
url="jdbc:oracle:thin:@127.0.0.1:1521:mysid"
maxActive="20" maxIdle="10" maxWait="-1"
username="myuser" password="C0iZc6o+6xqr0NggmuTo9gRtfowg0kyM8fqNQEJwAZE="
connectionProperties="algorithm=AES;mode=ECB;padding=PKCS5PADDING;keyFilename=/some/super/secure/location/keyfile"/>
<Resource name="jdbc/postgres" auth="Container"
factory="com.github.ncredinburgh.tomcat.SecureDataSourceFactory"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:5432/mydb"
maxActive="20" maxIdle="10" maxWait="-1"
username="myuser" password="C0iZc6o+6xqr0NggmuTo9gRtfowg0kyM8fqNQEJwAZE="
connectionProperties="algorithm=AES;mode=ECB;padding=PKCS5PADDING;keyFilename=/some/super/secure/location/keyfile"/>
The SecureDataSourceFactory extends the standard Tomcat DataSource and is configured using the DataSource property connectionProperties with the following values :
algorithm
Required. The name of the algorithm used to decrypt the password. Must be the name of one of the algorithm installed in the JVM using the Java Cryptography Architecture.
mode
Optional. The mode of the algorithm (where appropriate) to decrypt the password. Default value is NONE. For valid options consult the algorithm documentation.
padding
Optional. The padding used with the algorithm (where appropriate) to decrypt the password. Default value is NoPadding. For valid options consult the algorithm documentation.
keyFilename
Required*. The location of the file holding the secret key to be used with the algorithm to decrypt the password. This file must exist and be readable by the user of the Tomcat process.
keyLocator
Optional. The locator used to provide the decryption key. Default value is com.github.ncredinburgh.tomcat.KeyFile. Must be a class implementing the KeyLocator interface in Tomcat's classpath. See "Alternative KeySources" section below.
* Only required if the default key locator KeyFile is being used is used. See "Alternative Key Sources" section below.
The SecureTomcatDataSourceFactory library can be run on the command line to perform the necessary setup steps to create an encryption key and an encrypted password.
You can execute the SecureTomcatDataSourceFactory using the command line:
$ java -jar secure-tomcat-datasourcefactory-0.6.jar <command> <options>
or running the CLI with different locations for the required libraries:
$ java -cp "path/to/secure-tomcat-datasourcefactory-0.6.jar:/path/to/jakarta.xml.bind-api/*" com.github.ncredinburgh.tomcat.Main <command> <options>
The following commands are supported:
listKeyGenerators
Displays the names of the algorithms installed on this JVM that may be used to generate keys.
listCiphers
Displays the names of the algorithms installed on this JVM that may be used to encrypt passwords.
generateKey <algorithm> <keySize> <keyFilename>
Generates a random encryption key using the specified algorithm and key size into the named key file.
encryptPassword <password> <algorithm> <mode> <padding> <keyFilename>
Encrypts the given password using the specified algorithm/mode/padding with the named key file.
Encrypting a password and storing the secret key on the same server doesn't improve security. It only adds one more step to the malicious users job: namely decrypting your password with the key in the file. This is "security through obscurity". Likewise, embedding the secret key in a Java class in a JAR file doesn't improve security. The malicious user can decompile the class, retrieve the key and decrypt the encrypted password.
The range of solutions to this problem is outwith the scope of this discussion but if you want to use the default KeyFile implementation of the KeyLocator a more secure approach would be to ensure that the key file is only present when Tomcat starts. This could be achieved through storing the key file on a temporary filesystem that is only mounted during Tomcat startup - either physically through a USB memory stick or logically through a remote filesystem. After Tomcat startup is complete the filesystem is unmounted and the key is no longer available to the malicious user. The decrypted key is maintained only in the memory of the running Tomcat server.
By default the SecureTomcatDataSourceFactory expects to locate the decryption key in a file. This is because, by default, the decryptor is configured with a key locator of type KeyFile. The KeyFile locator requires the path to the key file in the property keyFilename.
Other more sophisticated implementations of KeyLocator can be written to interface with more advanced secret stores that offer features like one time use passwords and time limited access.
- Create a new Java project
- Add this library as a dependency of your build using the Maven coordinates from the Maven Central badge at the top of this page.
- Create a new class that implements the interface
com.github.ncredinburgh.tomcat.KeyLocator - Write your
locateKey()method to fetch the secret key for decrypting the configured password. - Build your project into a JAR file
- Deploy your JAR file alongside this library in the folder
${TOMCAT_HOME}/lib - Change your JNDI datasource configuration such that the
connectionsPropertiesvalue include thekeyLocatorproperty with the fully qualified class name of your new class. - Your done!
<Resource name="jdbc/postgres" auth="Container"
factory="com.github.ncredinburgh.tomcat.SecureDataSourceFactory"
type="javax.sql.DataSource" driverClassName="org.postgresql.Driver"
url="jdbc:postgresql://127.0.0.1:5432/mydb"
maxActive="20" maxIdle="10" maxWait="-1"
username="myuser" password="C0iZc6o+6xqr0NggmuTo9gRtfowg0kyM8fqNQEJwAZE="
connectionProperties="algorithm=AES;mode=ECB;padding=PKCS5PADDING;keyLocator=com.example.MyKeyLocator"/>
All contributions are welcome. Just fork this repository and send us a merge request. Just make sure your code meets the following requirements:
- You follow the Spring Java Style Guide
- Apply the style with
mvn spring-javaformat:apply - All the unit tests pass when running
mvn test
This project was inspired by an original article on JDev called "Encrypting passwords in Tomcat" (archived version retrieved 2026-08-06).
- Upgraded to JUnit Jupiter 6.1
- Source code formatting switched to
spring-javaformat
- Upgraded to Java 25
- Upgraded to Apache Tomcat 11.0 API
- Upgraded to Apache Tomcat 10.1 API
- Upgraded to Java 17
- Refactorings
- Library can be run from the command line to produce new encryption key and to encrypt password.
- Updates to README including instructions on how to run library on command line.
- First public release