http://coldfusion.com logo
#cfml-general
Title
# cfml-general
d

dick

04/25/2022, 10:49 AM
For security, in the past, I've used
hash()
with an application and a per-user salt to generate passwords. With a new app I'm working on, I'm looking at bcrypt but from what I've read it doesn't have the concept of an application and per-user salt. Is adding an application-wide workfactor enough? Should I also top-and-tail the password with the two salts as I've done in the past?
w

wil-shiftinsert

04/25/2022, 12:22 PM
Bcrypt is quite safe. There is a lot of info on bcrypt here https://auth0.com/blog/hashing-in-action-understanding-bcrypt/ Bcrypt has some standard output with algorithm, workfactor and hash already included
Copy code
$2a$12$R9h/cIPz0gi.URNNX3kh2OPST9/PgBkqquzi.Ss7KIUgO2t0jWMUW
\__/\/ \____________________/\_____________________________/
Alg Cost      Salt                        Hash
The whole point of the workfactor is that it takes time to check passwords (even valid ones). If your workfactor is high enough, password guessing is almost impossible.
d

dick

04/25/2022, 12:26 PM
So the old approach of adding a salt to your password is not relevant if you're using bcrypt?
So you won't bother
bcrypt( applicationSalt & password & userSalt, workfactor )
then, you'd just
bcrypt( password, workfactor )
and that would be considered safe?
w

wil-shiftinsert

04/25/2022, 12:42 PM
To which bcrypt library are you referring?
A bcrypt call needs a salt AND a workfactor, but some libraries are generating the salt for you internally, by using some random generated salt
d

dick

04/25/2022, 12:57 PM
Sorry, I'm looking at this on Forgebox - https://forgebox.io/view/BCrypt
w

wil-shiftinsert

04/25/2022, 1:00 PM
Yes, I am using that one most of the time. But I also used the plain java version some times. The forgebox version is easy because it is hiding some details, but that also makes it harder to understand.
Copy code
string function hashPassword(
        required string password,
        workFactor=variables.settings.workFactor,
        salt      =generateSalt( arguments.workFactor )
    ){
As you can see the workfactor is read from some settings here, and the salt is generated on the fly by calling the underlying java bcrypt.genSalt(workfactor) method. So in most cases you will be fine by just calling the hasPassword function with password argument only.
Not sure if you are using coldbox, in that case it is easy.|
d

dick

04/25/2022, 1:58 PM
Yes, I am using ColdBox. I did look at the guts of
hashPassword()
and saw that
salt
has to be an
int
like
workFactor
so it couldn't take my user salt.
Copy code
string function generateSalt( workFactor=variables.settings.workFactor ){
	return variables.bcrypt.genSalt( javaCast( "int", arguments.workFactor ) );
}
w

wil-shiftinsert

04/25/2022, 1:59 PM
no, I think that’s not true
bcrypt is generating a salt. Just dump
variables.bcrypt.genSalt( javaCast( "int", arguments.workFactor ) )
it to see if it is a number. genSalt is passing a number to the bcrypt library to determine the number of iterations, but I think it is generating a string.
d

dick

04/25/2022, 2:16 PM
Yes,
generateSalt()
does return a string but I can't
hashPassword( password='myUserPassword', salt='myUserSalt' )
because I get back _"Invalid salt version_"
w

wil-shiftinsert

04/25/2022, 2:20 PM
Indeed. I thing that’s specific to this bcrypt java library. For some stupid reason it detects the workfactor from the salt. Just see what’s going on here. If you do a hasspassword with a workfactor 12 but supply a genSalt(8), it ignores the workfactor 12. So in this case the bcrypt forgebox is slightly wrong, it tells you you can use a custom salt. But the only ‘custom’ salt is one which is generated by bcrypt. Not so custom at all, because it does so by default
But why do you want to supply a user salt? You don’t need it al all, and every hashed password has it’s own newly generated salt. Which is exactly what you want to prevent pwd guessing
d

dick

04/25/2022, 4:23 PM
I guess I'm so fixated on the "old" way of hashing passwords with an application salt, a user salt and
hash()
that I'm trying to apply this to bcrypt. Maybe I should relax and drop the application and user salt from my app. Thanks for your insight.
b

bdw429s

04/25/2022, 5:08 PM
@dick The short answer is you don't need to worry about salt at all yourself. bcrypt takes care of all of that for you and it creates a per-user salt automatically. All you need to do is give it the password
Every password will be automatically • salted • hashed X number of times based on your workfactor
Aim for a workfactor that takes 200-500ms IMO so it's fast enough a user won't notice it logging in. You want it to take some computing time to make brute force attacks unfeasible.
d

dick

04/26/2022, 9:27 AM
Thanks for the confirmation @bdw429s
j

Jochem

04/28/2022, 5:41 PM
What you call an "application salt" is typically called a "pepper". The important difference from a salt is that is must not be stored in the same place as the output of the hash so that if all output hashes leak (i.e. your database is breached), the attacker still misses a piece of the puzzle.That could be important to protect really weak password (like "987654321" or others from the top most occurring passwords), even if your workfactor causes a single hash to take half a second or so. For that it must have sufficient entropy (current NIST recommendation is 122 bit, so a random UUID would be good) .
But for most cases I consider a 12-character password with plain bcrypt and a workfactor to take 200ms good enough.
d

dick

04/29/2022, 8:20 AM
Ah, thanks @Jochem, I never knew that concept was called "pepper" but it makes sense! I've been using that technique for many years but with this new project coming along I thought I'd look at bcrypt which now seems to be the advised way to go.
3 Views