Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to correctly encode password using ShaPasswordEncoder?

I want to encode a password using ShaPasswordEncoder in my Spring app.

ShaPasswordEncoder sha = new ShaPasswordEncoder(256);
sha.setIterations(1000);
String hash = sha.encodePassword(password, salt);

But I don't what I should put to salt param. Can it be a static phrase (e.g. sT4t1cPhr453), or dynamic string different for every user (e.g. username or user ID)?

Edit:

I user custom AuthenticationProvider, so my security context looks like:

<authentication-manager>
   <authentication-provider ref="customAuthenticationProvider" />
</authentication-manager>

<beans:bean id="customAuthenticationProvider" class="com.app.cloud.auth.CustomAuthenticationProvider">

@Component("customAuthenticationProvider")
public class CustomAuthenticationProvider implements org.springframework.security.authentication.AuthenticationProvider {

    @Autowired
    private AuthService authService;

    @Override
    public Authentication authenticate(Authentication authentication)
            throws AuthenticationException,BadCredentialsException {
    //...
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
like image 995
misco Avatar asked Sep 06 '13 08:09

misco


2 Answers

In case you want to explicitly define the salt you can define the salt source:

Dynamic salt (based on the username property)

<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="sha-256">
            <salt-source user-property="username"/>
        </password-encoder>
    </authentication-provider>
</authentication-manager>

Static salt

<authentication-manager alias="authenticationManager">
    <authentication-provider user-service-ref="userDetailsService">
        <password-encoder hash="sha-256">
            <salt-source system-wide="MySalt" />
        </password-encoder>
    </authentication-provider>
</authentication-manager>

Recommended approach

If you are using Spring Security 3.1, the recommended approach would be to go for bcrypt, this automatically generates a salt and concatenates it.

<beans:bean id='bCryptPasswordEncoder' class='org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder'/>

<authentication-manager>
  <authentication-provider user-service-ref="userDetailsService">
          <password-encoder ref="bCryptPasswordEncoder"/>
  </authentication-provider>
</authentication-manager>

You can generate the user password like this:

String password = "p4ssword";
PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
String encodedPassword = passwordEncoder.encode(password);
like image 176
Sergi Almar Avatar answered Sep 21 '22 07:09

Sergi Almar


The principle behind salting hashes is that you are not vulnerable to rainbow tables. If you use static salt then its possible (but expensive) for someone to build a rainbow table for your salt. If the pickings are sweet, someone will do it.

Ideally your salt should be random (eg use bytes from a SecureRandom) and should be different for each user. You should store the salt alongside the hashed password, eg if you are using a database table then simply have a salt column.

The latest versions of Spring Security (3.1 and later) try to handle salt in an automatic, transparent manner. The password encoder will automatically generate random salt and append it to the hash instead of storing it separately (eg in different columns). Because hashes and the salt have a fixed length it is easy to determine which part of the data is which.

like image 21
Qwerky Avatar answered Sep 17 '22 07:09

Qwerky