Issue
Question:
Does Tomcat 9 Realm <CredentialHandler>
need the proper algorithm parameters to hash a password and authenticate a user from a password?
My webapp seems to be able to authenticate a user no matter what parameters I pass the PBKDF2WithHmacSHA512 algorithm, even when the attributes on the <CredentialHandler>
element are different, or without any attributes.
Is this the expected behavior of Tomcat's Realm? If so, how can this be? Is the Realm able to deduce the parameters from the composition of the hash?
Background:
Tomcat 9 offers container-managed security with a Realm based on Java's SecretKeyFactory algorithms.
I am using PBKDF2WithHmacSHA512, which has options:
- Iterations
- Key Length
- Salt Length
My CredentialHandler as defined in my webapp's context.xml
is
<CredentialHandler
className="org.apache.catalina.realm.SecretKeyCredentialHandler"
algorithm="PBKDF2WithHmacSHA512"
iterations="100000"
keyLength="256"
saltLength="16">
</CredentialHandler>
A Tomcat installation offers CLI access to the hashing algorithm at CATALINA_HOME/bin/digest.[bat|sh]
. (See the Tomcat 9 Realm Configuration HOW-To for more details.)
No matter the options I pass to the CLI hashing algorithm, Tomcat is able to authenticate the user correctly from the DataSource Realm (MySQL database). The password can be successfully authenticated against both of the following:
Example #1 matches <CredentialHandler>
:
$ $CATALINA_HOME/bin/digest.sh -a PBKDF2WithHmacSHA512 -i 100000 -s
16 -k 256 -h org.apache.catalina.realm.SecretKeyCredentialHandler passw0rd
passw0rd:d0c315b015272b531b0a82cec220d4a1$100000$7ac32ed573fe81e75f611a46622573515
ad11d731dcae4839973ae2702774c51
Example #2 different parameters:
$ $CATALINA_HOME/bin/digest.sh -a PBKDF2WithHmacSHA512 -i 100 -s 1 -k 128
-h org.apache.catalina.realm.SecretKeyCredentialHandler passw0rd
passw0rd:47$100$0e4790b617fa24ee324d55bed38ad4b0
Also See
Solution
Yes, this is the expected behavior of Tomcat Realm with a SecretKeyCredentialHandler as CredentialHandler defined. Tomcat does not need the iterations, salt or key parameters in context.xml, to authenticate a user from a password.
How is this possible?
If you look into the tomcat documentation of the SecretKeyCredentialHandler, you will notice that the stored passwords is defined as:
salt $ iterationCount $ encodedCredential - a hex encoded salt, iteration code and a hex encoded credential, each separated by $.
The salt and iterationCount used for encryption are part of the stored password. Tomcat don't uses the values of the CredentialHandler-Tag from context.xml for decryption. It uses the values from the password itself. If you look inside your two generated passwords, you will find salt and iterationCount in it, formated in the defined pattern.
Why do i have to set the values in context.xml anyway?
You don't have to. For decryption, only the algorithm-attribute value from context.xml it used. So, for what are the other attributes? Reading carefully the Tomcat documentation gives the answer:
The CredentialHandler can also be used to generate a new stored version of a given credential that would be required, for example, when adding a new user to a Realm or when changing a user's password.
and
iterations - The number of iterations to use when creating a new stored credential from a clear text credential.
saltLength - The length of the randomly generated salt to use when creating a new stored credential from a clear text credential.
keyLength - The length of key to generate for the stored credential. If not specified, a default of 160 is used.
These CredentialHandler-Tag attributs from context.xml are used when creating a new password via CredentialHandler (see method mutate in API). Its used for encryption to create a new password, not for decryption of existing passwords.
Answered By - VinZ