Encoding password using DIGEST in Apache Tomcat 8.5.x and 9.0.x
search cancel

Encoding password using DIGEST in Apache Tomcat 8.5.x and 9.0.x

book

Article ID: 297383

calendar_today

Updated On:

Products

Support Only for Apache Tomcat

Issue/Introduction

When upgrading from Tomcat 7.0 to 8.5 or 9.0, the digest.sh/digest.bat script does not work. It used to return the same value for the same password value all the time.

In Tomcat 8.5 or 9.0, the digest.sh/digest.bat script returns a different value for the same password value.




Environment

Product Version: Other

Resolution


The release of Tomcat 8.5 (and later) provides an improved security to support pluggable CredentialHandler and support new algorithms. The Credential Handler implementation has the addition of "salting" and "iterations" as well as backward compatibility.  


Following is a sample configuration for Tomcat 7.0 with digest password:


Usage:
digest.[bat|sh] -a <algorithm> [-e <encoding>] <credentials>
Fore more info: http://tomcat.apache.org/tomcat-7.0-doc/realm-howto.html#Digested_Passwords

 

./digest.sh  -a md5 s3cret
S3cret:33e1b232a4e6fa0028a6670753749a17

 

            
Note: digest.sh command is located in $CATALINA_BASE/bin directory

Configuration:
     conf/tomcat-users.xml

<?xml version="1.0"?>

<tomcat-users>

<user username="tomcat" password="33e1b232a4e6fa0028a6670753749a17" roles="manager-gui"/>

</tomcat-users>


     conf/server.xml

   <Realm className="org.apache.catalina.realm.LockOutRealm">

  <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" digest="md5"/>

 </Realm>

 

 

Starting in Tomcat 8.5.x digest was improved as follows:

 
Usage: 

digest.[bat|sh] [-a <algorithm>] [-e <encoding>] [-i <iterations>] [-s <salt-length>] [-k <key-length>] [-h <handler-class-name>] <credentials>
For more info: https://tomcat.apache.org/tomcat-8.5-doc/realm-howto.html#Digested_Passwords

 

If you are migrating from Tomcat 7.0.x to Tomcat 8.5.x (or later) the you can still use the old password. In generating the same password, add option "-s 0" . This turns off salting as shown.

 

$ ./digest.sh  -a md5 -s 0  s3cret
s3cret:33e1b232a4e6fa0028a6670753749a17                

Note: same generated password as in Tomcat 7

 
Then make the following changes in server.xml to implement MessageDigestCredentialHandler)

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

                       resourceName="UserDatabase">

                   <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" 

                        algorithm="MD5" />

           </Realm>

Note: digest.sh will output a different hash every time if “-s 0” is omitted. It defaults to a saltLength="32" iterations=”1”
There is no required change for conf/tomcat-users.xml

       
 

Following are recommended configurations options when using digest to encrypt password

 

1) Use MessageDigestCredentialHandler with salt and iteration

To further improve security, it’s recommended to use the following on tomcat 8.5 and later

  • Salted password
  • Many iteration
     

         Usage:

$ ./digest.sh  -a md5 -s 16 -i 10000 s3cret

s3cret:8208b5051cdd2b35cfba7f0b70b57e7f$10000$f4afe3c9c24190d0a331fd890d4992c3

 


         Configuration:
             conf/tomcat-users.xml

<?xml version="1.0"?>

<tomcat-users>

<user username="tomcat" password="8208b5051cdd2b35cfba7f0b70b57e7f$10000$f4afe3c9c24190d0a331fd890d4992c3" roles="manager-gui"/>

</tomcat-users>

 

 
             conf/server.xml
           

 <Realm className="org.apache.catalina.realm.UserDatabaseRealm"

                       resourceName="UserDatabase">

                   <CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler" algorithm="MD5" saltLength="16" iterations=”10000”/>

                </Realm>

2) Use Key-derivation algorithm

For more security, key-derivation algorithm - PBKDF2 can be used by implementing SecretKeyCredentialHandler


   Usage: 

$ ./digest.sh -a PBKDF2WithHmacSHA512 -i 10000 -s 16 -k 256 -h org.apache.catalina.realm.SecretKeyCredentialHandler s3cret

s3cret:0b0a9051ee0e84cc7342aec4df96962f$10000$5de2b3d90d7491e6f9866c3d2cd3c436c4066255a0364a1d5f517a7e86a75b95

 

     Configuration:
             conf/tomcat-users.xml
           

 <?xml version="1.0"?>

<tomcat-users>

<user username="tomcat" password="0b0a9051ee0e84cc7342aec4df96962f$10000$5de2b3d90d7491e6f9866c3d2cd3c436c4066255a0364a1d5f517a7e86a75b95" roles="manager-gui"/>

</tomcat-users>

 

conf/server.xml

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

                       resourceName="UserDatabase">

                   <CredentialHandler

                             className="org.apache.catalina.realm.SecretKeyCredentialHandler"

                               algorithm="PBKDF2WithHmacSHA512" saltLength="16" iterations="10000" keyLength="256" />

                </Realm>

3) Use of NestedCredentialHandler

This combines the aforementioned #1 and #2. It allows both types to be implemented concurrently. This allows seamless upgrades between algorithms.  

 

The example below illustrates the use of both SecretKeyCredentialHandler and MessageDigestCredentialHandler with no salt/iteration.

 
    Configuration:
             conf/tomcat-users.xml

<?xml version="1.0"?>

<tomcat-users>

<user username="tomcat-old" password="33e1b232a4e6fa0028a6670753749a17" roles="manager-gui"/>

<user username="tomcat-new" password="0b0a9051ee0e84cc7342aec4df96962f$10000$5de2b3d90d7491e6f9866c3d2cd3c436c4066255a0364a1d5f517a7e86a75b95" roles="manager-gui"/>

</tomcat-users>


Note:both users “tomcat-old” and “tomcat-new” will be authenticated successfully

   
          conf/server.xml

<Realm className="org.apache.catalina.realm.UserDatabaseRealm"

                       resourceName="UserDatabase">

                   <CredentialHandler

                           className="org.apache.catalina.realm.NestedCredentialHandler">

                    <CredentialHandler

                            className="org.apache.catalina.realm.SecretKeyCredentialHandler"

                             algorithm="PBKDF2WithHmacSHA512" saltLength="16" iterations="10000" keyLength="256" />

                      <CredentialHandler

                             className="org.apache.catalina.realm.MessageDigestCredentialHandler"

                               algorithm="MD5" />

                    </CredentialHandler>

                </Realm>


References for Tomcat 8.5 and 9.0
https://tomcat.apache.org/tomcat-8.5-doc/realm-howto.html#Digested_Passwords
https://tomcat.apache.org/tomcat-9.0-doc/realm-howto.html#Digested_Passwords