0

I have this jOOQ 3.14.4, Scala 2.13 code, that is mixed with some deprecated Play code:

val user = Option(sql
  .selectFrom(USER)
  .where(USER.EMAIL.equal(email))
  .and(USER.PASSWORD.equal(crypto.sign(password)))
  .fetchOne())

Note that email and password are Strings.

Now, I want to replace the code that uses the Play deprecated Crypto with a new Java method (which I got from the jBCrypt library):

public static boolean checkpw(String plaintext, String hashed)

1. How can I use BCrypt.checkpw(...) inside the jOOQ code?

equal does not return a boolean, and how do I extract the actual String value in the USER.PASSWORD TableField?

Example of using the BCrypt.checkpw method:

// Check that an unencrypted password matches one that has
// previously been hashed
if (BCrypt.checkpw(candidate, hashed))
    System.out.println("It matches");
else
    System.out.println("It does not match");

2. Is jBCrypt considered secure, from a cryptographic point of view, for the purpose of encrypting passwords for saving them in a production database?

rapt
  • 11,810
  • 35
  • 103
  • 145

1 Answers1

3

I don't know the answer to your second question (which I recommend you ask in a new question. The two aren't related). Here's the answer to your first one:

  1. How can I use BCrypt.checkpw(...) inside the jOOQ code?

With this method signature, you'll have to fetch the hashed password from your database, instead of checking it with SQL. You cannot execute the Java logic behind checkpw in the database. So do this, instead:

val user = Option(sql
  .selectFrom(USER)
  .where(USER.EMAIL.equal(email))
  .fetchOne())
  .filter(u => BCrypt.checkpw(password, u.getPassword))
Lukas Eder
  • 211,314
  • 129
  • 689
  • 1,509
  • Awesome! Seems like that's what I can do if I have to use `BCrypt.checkpw`. It think you rely on the assumption that `email` is used by a single user, otherwise it may return more than one record and the performance may be bad. I also looked into what `checkpw` actually does, and it does call the hash method `BCrypt.hashpw` but does more than just checking if `hashpw(password, salt) == saved_password` (it's not clear to me why). If I just do a comparison of the saved and newly calculated hashes, then with jooq I can do `.and(USER.PASSWORD.equal(BCrypt.hashpw(password, BCrypt.gensalt())))` – rapt Dec 27 '20 at 14:21
  • @rapt: I very much rely on the assumption that an email is unique among users, because you do, too in your query, and I can't imagine a system, nor have I ever seen one, where the opposite would make sense, although, I'm curious to be corrected. – Lukas Eder Dec 27 '20 at 17:05
  • You are right, the email is unique among users. Which is useful here. — I meant that in other cases when there is a need to do `fetch` before using some filtering algorithm on the records retrieved from the database, it might be that many records are retrieved, not just one. Gladly this was not the case here. – rapt Dec 27 '20 at 19:02