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)?
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);
}
}
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);
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With