Search code examples
hashshiro

How do I specify number of Hash iterations to be used in Apache Shiro?


I'm working with a JSF2 application where I'd like to use Apache Shiro. I have it up-and-running though I don't know how to specify the number of Hash iterations to be used.

shiro.ini

[main]

user = com.nivis.filter.FacesAjaxAwareUserFilter    
shiro.loginUrl = /faces/login.xhtml    
user.loginUrl = /faces/login.xhtml

jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
jdbcRealm.permissionsLookupEnabled = true    
jdbcRealm.authenticationQuery = SELECT password FROM app_user WHERE username = ?  

dataSource = org.apache.shiro.jndi.JndiObjectFactory       
dataSource.requiredType = javax.sql.DataSource      
dataSource.resourceName = JNDImysql  

jdbcRealm.dataSource = $dataSource      
securityManager.realms = $jdbcRealm

passwordService = org.apache.shiro.authc.credential.DefaultPasswordService    
passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher    
passwordMatcher.passwordService = $passwordService

jdbcRealm.credentialsMatcher = $passwordMatcher

[urls]  

/faces/login.xhtml = user      
/faces/index.xhtml = user      
/faces/app/** = user  

It does work to get the password hashed even though I do not explicitly specify a hash service. I saw an example using:

hashService = org.apache.shiro.crypto.hash.DefaultHashService
hashService.hashIterations = 10000
hashService.hashAlgorithmName = SHA-256
passwordService.hashService = $hashService

Which I tried to use, although it didn't make any difference. As it seems to be enough to use only the PasswordService to get the password hashed, I'd like to know if there's a way of specifying how many hash iterations to use?


Solution

  • You can try to do it like this:

    # Configure Data Source --> see web.xml for full configuration
    dataSource = org.apache.shiro.jndi.JndiObjectFactory
    dataSource.resourceName = <resource name>
    dataSource.resourceRef = true
    
    # Create JDBC-Realm to connect to the Datasource and set the authenticationQuery
    jdbcRealm = org.apache.shiro.realm.jdbc.JdbcRealm
    jdbcRealm.dataSource = $dataSource
    jdbcRealm.authenticationQuery = SELECT password FROM <user table> WHERE email = ?
    
    # Configure JDBC realm password hashing.
    hashService = org.apache.shiro.crypto.hash.DefaultHashService
    hashService.hashIterations = <number of iterations>
    hashService.hashAlgorithmName = SHA-256
    hashService.generatePublicSalt = true
    # privateSalt needs to be base64-encoded in shiro.ini but not in the Java code!
    hashService.privateSalt = <base64-encoded Salt string>
    passwordMatcher = org.apache.shiro.authc.credential.PasswordMatcher
    
    passwordService = org.apache.shiro.authc.credential.DefaultPasswordService
    passwordService.hashService = $hashService
    passwordMatcher.passwordService = $passwordService
    
    jdbcRealm.credentialsMatcher = $passwordMatcher
    

    Note: this example also uses a private salt. To add more security against passwords being calculated using rainbow tables / brute force attacks, I strongly recommend using a salt. The above example code might not be the best way to handle salting, but it works fine. Also take care that a Salt needs to be base64-encoded in the shiro.ini but not in the java code.