Chapter 8. Password Encryption using PicketLink IDM Framework
8.1. Hashing and Salting of Passwords in PicketLink IDM
The portal uses PicketLink IDM framework (http://www.jboss.org/picketlink/IDM) to store information about identity objects (users/groups/memberships). For better security, PicketLink IDM does not save user passwords into database in plaintext, but it uses
CredentialEncoder, which encodes password and saves the encoded form into PicketLink IDM database. Later when the user wants to authenticate, they need to provide their password in plaintext through a web login form. The provided password is then encoded and compared to an encoded password in the PicketLink IDM database. The portal is then able to authenticate the user based on this comparison.
8.2. Implementing Credential Encoder
8.2.1. Default Implementation of CredentialEncoder
Default implementation of CredentialEncoder is DatabaseReadingSaltEncoder. It uses password hashing with a SHA-256 algorithm, and salting with random salts. Those salted hashes are then stored in the database.
Warning
The default DatabaseReadingSaltEncoder is safe solution, but it is not backward compatible with previous releases of the portal before v6.0. If migrating from older release of the portal, switch to HashingEncoder and configure it. See the Migration Guide for more info.
If starting from fresh database (no migration from a previous portal release), it is sufficient to keep the default choice provided by DatabaseReadingSaltEncoder, or possibly switch to FileReadingSaltEncoder.
8.2.2. Choosing CredentialEncoder Implementation
The implementation of CredentialEncoder is configured in Picketlink IDM configuration file
JPP_HOME/gatein/gatein.ear/portal.war/WEB-INF/conf/organization/picketlink-idm/picketlink-idm-config.xml.
Usually the most important are options of realm idm_portal starting with prefix credentialEncoder. Possible implementations are HashingEncoder, DatabaseReadingSaltEncoder, and FileReadingSaltEncoder.
Note
If you are using LDAP, the location of Picketlink IDM configuration file can be different.
8.2.3. Configuring Hashing Encoder
This implementation uses only hashing of passwords with MD5 algorithm without salting. It is not the safest solution but it is backward compatible with the previous portal releases, so there are no issues with database migration. The configuration is as follows:
Example 8.1. Configuration of Hashing Encoder
<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.HashingEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>MD5</value> </option>
8.2.4. Configuring DatabaseReadingSaltEncoder
This is the default choice. This implementation provides salting of password in addition to hashing. The salt is unique for each user, so it is much more complicated to decrypt password via brute force, if an attacker steals encoded passwords from your database. The salt is generated randomly for each user and stored in the PicketLink IDM database as an attribute. Random generation of salt ensures that all users have different salts, so even if two users have the same password, the encoded password in database will be different for them. Here is configuration example, which is using SHA-256 algorithm for hashing (more secure than MD5) and algorithm SHA1PRNG for generation of random salts.
<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.DatabaseReadingSaltEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>SHA-256</value> </option> <option> <name>credentialEncoder.secureRandomAlgorithm</name> <value>SHA1PRNG</value> </option>
8.2.5. Configuring FileReadingSaltEncoder
The FileReadingSaltEncoder also uses hashing and salting, so it is similar to the previous encoder. Theoretically it is even more secure, because salts are not stored in the PicketLink IDM database together with passwords. Salt for each user is generated from
saltPrefix and the user's user name. saltPrefix is read from a file on the host computer.
Example 8.2. FileReadingSaltEncoder
This example describes a possible configuration of FileReadingSaltEncoder.
<option> <name>credentialEncoder.class</name> <value>org.picketlink.idm.impl.credential.FileReadingSaltEncoder</value> </option> <option> <name>credentialEncoder.hashAlgorithm</name> <value>SHA-256</value> </option> <option> <name>credentialEncoder.fileLocation</name> <value>/salt/mysalt.txt</value> </option>
Important
The
CredentialEncoder in Example 8.2, “FileReadingSaltEncoder” is actually used only for encoding of passwords in PicketLink IDM database. It is not used for LDAP. PicketLink IDM LDAP implementation (LDAPIdentityStore) sends passwords to the LDAP server in plain form, because password encoding is usually provided by LDAP server itself. For example OpenDS 2 uses SHA1 based hashing of passwords with random generation of user salt (quite similar to the DatabaseReadingSaltEncoder implementation).
The
FileReadingSaltEncoderis arguably the most secure of all options, but in addition to DatabaseReadingSaltEncoder, you need to set the file with salt.
The
/salt/mysalt.txt file must exist and must be readable by the user who starts the portal. The file must be properly secured so that it is not readable by every user. The content of the file can be a random phrase, such as a4564dac2aasddsklklkajdgnioiow.
8.2.6. Migration of Credential Encoder
As mentioned previously, our current default implementation DatabaseReadingSaltEncoder is not compatible with previous releases of GateIn Portal. In GateIn Portal 3.5 and older, we used MD5 hashing without salts. So to be backwards compatible, you will need to switch from default implementation of DatabaseReadingSaltEncoder and configure HashingEncoder with MD5 hashes. Without this change, your users cannot login into GateIn Portal because their passwords are stored in Picketlink IDM database as MD5 hashes, but current default encoder is using SHA-256 and salts, so comparisons will be different.
We decided to do this change and switch default algorithm, because MD5 is nowadays not treated as very secure solution.