Collectives™ on Stack Overflow
Find centralized, trusted content and collaborate around the technologies you use most.
Learn more about Collectives
Teams
Q&A for work
Connect and share knowledge within a single location that is structured and easy to search.
Learn more about Teams
I'm trying to implement authentication using BCrypt, in my Play 2.1. Java application, but I'm getting
Invalid salt version exception
when I'm trying to authenticate the user.
This is my stack trace
play.api.Application$$anon$1: Execution exception[[IllegalArgumentException: Invalid salt version]]
at play.api.Application$class.handleError(Application.scala:289) ~[play_2.10.jar:2.1.0]
at play.api.DefaultApplication.handleError(Application.scala:383) [play_2.10.jar:2.1.0]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anon$2$$anonfun$handle$1.apply(PlayDefaultUpstreamHandler.scala:132) [play_2.10.jar:2.1.0]
at play.core.server.netty.PlayDefaultUpstreamHandler$$anon$2$$anonfun$handle$1.apply(PlayDefaultUpstreamHandler.scala:128) [play_2.10.jar:2.1.0]
at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10.jar:2.1.0]
at play.api.libs.concurrent.PlayPromise$$anonfun$extend1$1.apply(Promise.scala:113) [play_2.10.jar:2.1.0]
java.lang.IllegalArgumentException: Invalid salt version
at org.mindrot.jbcrypt.BCrypt.hashpw(BCrypt.java:664) ~[jbcrypt-0.3m.jar:na]
at org.mindrot.jbcrypt.BCrypt.checkpw(BCrypt.java:763) ~[jbcrypt-0.3m.jar:na]
at model.operations.DistrictOperations.authenticate(DistrictOperations.java:24) ~[na:na]
at controllers.Application.authenticateDistrict(Application.java:26) ~[na:na]
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$2$$anonfun$apply$2.apply(routes_routing.scala:133) ~[na:na]
at Routes$$anonfun$routes$1$$anonfun$applyOrElse$2$$anonfun$apply$2.apply(routes_routing.scala:133) ~[na:na]
I'm using following maven repository: http://mvnrepository.com/artifact/org.mindrot/jbcrypt/0.3m
My code is based on the documentation, thus
district.setPassword(BCrypt.hashpw(json.findPath("password").getTextValue(), BCrypt.gensalt()));
For saving the password (I'm also checking the password for being null)
BCrypt.checkpw(password, d.getPassword());
For checking if the entered password is correct, where password is String and d.getPassword() is hashed password.
I don't know if this is relevant information, but to be precise I'm using hibernate for ORM and PostgreSQL 8.4 as DB.
I'm kind of stuck in here so I'm asking if anyone could help me out. Than you very much in advance.
For others encountering the same exception, check that you have the BCrypt.checkpw
parameters the right way round. (I didn't and therefore found this question before I realised my silly mistake.)
Or as the OP answered himself, log/debug the value of the hashed password to double check you are actually comparing a hashed password! It should be a 60-char string in the format
$2a$10$llw0G6IyibUob8h5XRt9xuRczaGdCm/AiV6SSjf5v78XS824EGbh.
–
–
jBcrypt is too old and actually unmaintained. Please consider switching to a new implementation of that library to handle the new $2y$
versions.
I solved this using this pure Java library https://github.com/patrickfav/bcrypt, adding it in my current Scala project.
With the following function I can finally verify the hashes created with VERSION_2Y
:
* Verifies an encrypted password against the expected value
* @link https://github.com/patrickfav/bcrypt
* @param hash The hashed password (encypted with BCrypt version $2Y$)
* @param password The unencrypted password string
private def verifyBcryptHash(hash: String, password: String): Boolean = {
if (hash == null || hash.trim.isEmpty)
false
BCrypt
.verifyer()
.verifyStrict(
password.toCharArray(),
hash.toCharArray(),
BCrypt.Version.VERSION_2Y
.verified
You have to make sure that the first argument is the plaintext and the second one is the hashed password.
This is the function's declaration :
public static boolean checkpw(String plaintext, String hashed)
in my case, I have used {bcrypt}
as a prefix during the insertion into db.
instance
{bcrypt}$2a$12$Yb3YagKV8B3AXoY2p/Ldk.L2maVKfNlr2dedk4ZUs/YUlalS8EzYu
when I retrieve the password the whole value including prefix
will be returned. So I have excluded the prefix from the hashing
value.
String prefix= "{bcrypt}";
String hash_pw= user.getPassword().substring((prefix.length());
BCrypt.checkpw(loginRequest.getPassword(),hash_pw);
–
–
–
In my case, I got this salt revision error because of applying hashed password from https://bcrypt-generator.com into my server's bcrypt checker (spring java security). However, with another same plain password but hashed from https://www.javainuse.com/onlineBcrypt, it worked and verified the password. Log rounds are configured the same (16).
I assumed that my case was because of using a different bcrypt encoder although some might work with a different one.
But, it is guaranteed for sure that hashed password doesn't have this issue if the bcrypt generator and the checker are from the same library.
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.