I need to use Container Managed Security and Authentication in my latest project. And I have a couple of queries regarding how to configure a Credential Handler.
The algorithm field of MessageDigestCredentialHandler is a string that can take any of the values described here: http://docs.oracle.com/javase/7/docs/technotes/guides/security/StandardNames.html#MessageDigest
The difference between MessageDigestCredentialHandler and SecretKeyHandler is the algorithms to use, I think, SecretKeyHandler is more secure because of the javax.crypto.SecretKeyFactory.
I can't provide any sample of configuration, but when I worked with TomcatRealms implementing custom AuthorizationProviders I always configured it in META-INF/context.xml
Finally, I would like to advise you, for years I have bee working with custom AuthorizationProviders, but now I migrated all of them to Spring Security.
NestedCredentialHandler is for cases when you have multiple digest methods, for example you have used MessageDigest in the past but now you want to switch a more secure PBKDF2-SHA512 configuration, and don't want to make already configured passwords invalid.
For example:
<CredentialHandler className="org.apache.catalina.realm.NestedCredentialHandler">
<CredentialHandler className="org.apache.catalina.realm.SecretKeyCredentialHandler"
algorithm="PBKDF2WithHmacSHA512"
iterations="100000"
keyLength="256"
saltLength="16"
/>
<CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler"
algorithm="SHA-256"
iterations="1000"
keyLength="256"
saltLength="8"
/>
</CredentialHandler>
<!-- NOTE: keyLength is in bits, saltLength is in bytes. 16 bytes = 128 bits -->
This would go inside your Realm element.
SecretKeyCredentialHandler was introduced in Tomcat 8.0.15 and uses SecretKeyFactory from the javax.crypto API rather than the old method (MessageDigest) to mutate the password. SecretKeyFactory allows for better algorithms such as PBKDF2 with HMAC-SHA-512 rather than plain hash algorithms such as SHA-512. The old method is since available via MessageDigestCredentialHandler, which is equivalent of setting the digest attribute on the Realm element directly.
Please note, setting the digest attribute directly or using MessageDigestCredentialHandler without the optional iteration attribute (8.0.15+ only) will only do one iteration. This is NOT secure.
As for what algorithms are available for SecretKeyFactory, the Java Cryptography Architecture Standard Algorithm Name Documentation for JDK 8 is the best reference I could find, but it doesn't list all combinations explicitly. These were the ones I found working on my platform (Linux 3.13.0, Oracle JDK 1.8.0_111), but yours may support other combinations.
To answer the first point, here's a comparison of the <Realm>
from my context.xml before and after the switch to Tomcat 8:
Before:
<Realm className="org.apache.catalina.realm.DataSourceRealm"
dataSourceName="jdbc/myDataSource"
roleNameCol="role" userCredCol="password" userNameCol="loginid"
digest="md5"
userRoleTable="userroles" userTable="users"
localDataSource="true" />
After:
<Realm className="org.apache.catalina.realm.DataSourceRealm"
dataSourceName="jdbc/myDataSource"
roleNameCol="role" userCredCol="password" userNameCol="loginid"
userRoleTable="userroles" userTable="users" localDataSource="true">
<CredentialHandler
className="org.apache.catalina.realm.MessageDigestCredentialHandler"
algorithm="md5" />
</Realm>
I have a requirement to deploy the same myapp.war binary file to Tomcat7 and Tomcat8 environments. Using this configuration both environments work fine.
myapp/META-INF/context.xml
<Realm className="org.apache.catalina.realm.DataSourceRealm"
dataSourceName="jdbc/myapp" localDataSource="true" digest="SHA-256"
userTable="user_role_v" userNameCol="username" userCredCol="password"
userRoleTable="user_role_v" roleNameCol="role">
<CredentialHandler className="org.apache.catalina.realm.MessageDigestCredentialHandler"
algorithm="SHA-256" iterations="1" saltLength="0" encoding="ISO-8859-1" />
</Realm>
You see a warning in catalina log file at startup for unknown parameter but it does not matter.