Michael
Michael

Reputation: 10319

How to use SHA-512 with o.s.s.crypto.password.StandardPasswordEncoder?

I need to use SHA-512 in my code to hash passwords.

Now I use o.s.s.authentication.encoding.PasswordEncoder while it is initialized to ShaPasswordEncoder(512).

In addition, o.s.s.authentication.encoding.PasswordEncoder supports method String encodePassword(String rawPass, Object salt) that allow to store salt separately from the password.

Unfortunately, o.s.s.authentication.encoding.PasswordEncoder is deprecated.

Also, o.s.s.crypto.password.StandardPasswordEncoder supports only SHA-256.

In addition it is final class and does not allow its overloading to support SHA-512.

How to use SHA-512 with o.s.s.crypto.password.StandardPasswordEncoder? Why there is no public method that allows to pass salt stored externally?

Upvotes: 1

Views: 2089

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 148900

Well I must admit that it is not the most coherent part in Spring Security ... DaoAuthenticationProvider.getPasswordEncoder() returns a o.s.s.authentication.encoding.PasswordEncoder which is deprecated according to the javadoc !

The trick is that DaoAuthenticationProvider.getPasswordEncoder() takes an Object as parameter, and this Object may be a o.s.s.authentication.encoding.PasswordEncoder ... but do not try to do a get !

As per my understanding, o.s.s.crypto.password.StandardPasswordEncoder is an example with medium security and a fixed SHA-256. If you want a higher level of security, you can use a o.s.s.crypto.password.BCryptPasswordEncoder which uses the robust BCrypt algorythm with a configurable level. After viewing the sources, I can confirm than both use salt and store it internally in encoded password.

Perhaps somebody from Spring Security team could explain the reasons for those (discutable) choices regarding the impossibility to change digest algorythm but I cannot ; maybe it is simply because for using SHA it is enough to stick to the (not deprecated) ShaPasswordEncoder. I simply noted this remark in StandardPasswordEncoder : If you are developing a new system, BCryptPasswordEncoder is a better choice both in terms of security and interoperability with other languages.

So, either you follow the advice of the author of StandardPasswordEncoder, and use directly BCryptPasswordEncoder, or you will have to roll your own.

It is enough to copy the source of StandardPasswordEncoder, to stick to the org.springframework.security.crypto.password package, because there are package private imports, and modify the 2 argument constructor to be public as :

public ConfigurablePasswordEncoder(String algorithm, CharSequence secret) { ... }

All this is more a collections of workarounds than a clean solution, but I never found a better way !

As a conclusion, I would say that only the interface o.s.s.authentication.encoding.PasswordEncoder is deprecated, because it stores the salt outside of the encoded password. So it should not be used for further developpement of password encoders. But its implementation classes are not deprecated (neither in last 3.2 release version, nor in 4.0.0M2) and you can safely keep on using ShaPasswordEncoder if it meets your requirements.

Upvotes: 1

Related Questions