0

I'm using Shiro with Spring MVC to login users. I configure Shiro in applicationContext.xml (no INI file).

This is the realm configuration:

  <bean id="myRealm" class="org.apache.shiro.realm.jdbc.JdbcRealm">
    <property name="dataSource" ref="dataSource"/>
    <property name="authenticationQuery" value="select password from usuarios where email = ?"/>
    <property name="credentialsMatcher">
        <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
              <property name="storedCredentialsHexEncoded" value="false"/>
              <property name="hashIterations" value="1024" />
        </bean>
    </property>
  </bean>

This is my code generating salt and hash when the user registers:

RandomNumberGenerator rng = new SecureRandomNumberGenerator();
Object salt = rng.nextBytes();

String hashedPasswordBase64 = new Sha256Hash(password, salt, 1024).toBase64();

u.setPassword(hashedPasswordBase64);
u.setSalt(salt.toString());

usuarioDao.saveUsuario(u);

Here saveUsuario(u) calls the DAO to persist the user in MySQL. I guess that the salt.toString() is wrong.

The user table is:

CREATE TABLE usuarios (
  id INTEGER AUTO_INCREMENT,
  nombre VARCHAR(50),
...
  password VARCHAR(50),
  salt VARCHAR(50),
...
  PRIMARY KEY (id)
);

Questions are: - Which type should be the hash field in the DB? The hash is created by rng.nextBytes and is of type Object. - How do I declare the field or the query to HashedCredentialsMatcher so it can authenticate properly?

  • Can be Varchar but 256 size, use the jar _commons-codec_ in your classpath and try it `setSalt(new org.apache.commons.codec.binary.Base64().encodeToString(salt))` – user2669657 Feb 07 '16 at 23:53

2 Answers2

1

First, please read Thomas Pornin's canonical answer to How to securely hash passwords.

Then, note that Java 8 does have PBKDF2-HMAC-SHA-512 available now as PBKDF2WithHmacSHA512 - use that instead. SHA-512 in particular has 64-bit operations that reduce the advantage GPU based attackers have. Use more iterations than just 1024, as well - see what your system can handle comfortably under load!

Use those, or BCrypt, or SCrypt. Use at least a 12 byte cryptographically random salt.

Do not request more than 64 (binary) bytes out of PBKDF2-HMAC-SHA-512, more than 32 (binary) bytes out of PBKDF2-HMAC-SHA-256, or more than 20 (binary) bytes out of PBKDF2-HMAC-SHA-1, or you actively give attackers an advantage.

You can absolutely store both the hash and the salt in the database in BINARY() fields, or you could convert them to Base64 or hexadecimal; that's all up to you. BINARY() is the smallest, and requires no conversions going in or coming out.

Anti-weakpasswords
  • 2,604
  • 20
  • 25
0

I have found the answer in this topic: how to get/set the salt for a JdbcRealm

I extended JdbcRealm with:

public class JdbcSaltRealm extends JdbcRealm {

    public JdbcSaltRealm() {
        setSaltStyle(SaltStyle.COLUMN);
    }
}

Then I changed myRealm in applicationContext.xml to:

  <bean id="myRealm" class="ar.com.yojunto.webapp.security.JdbcSaltRealm">
    <property name="dataSource" ref="dataSource"/>
    <property name="authenticationQuery" value="select password, salt from usuarios where email = ?"/>
    <property name="credentialsMatcher">
        <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
              <property name="hashAlgorithmName" value="SHA-256" />
              <property name="hashIterations" value="1024" />
        </bean>
    </property>
  </bean>

and finally changed the DB to:

  password VARCHAR(64),
  salt VARCHAR(50),

I don´t know how strong is the salt with this algorithm, but it worked fine.

Community
  • 1
  • 1