Is there a practical difference between generate bcrypt salt and hash on separate function calls or auto-gen a salt and hash?

I honestly tried my best to find the answer here or anywhere else.
Bcrypt documentation states that there are 2 techniques to hash/salt a password:
Technique 1 (generate a salt and hash on separate function calls):

bcrypt.genSalt(saltRounds, function(err, salt) {
    bcrypt.hash(myPlaintextPassword, salt, function(err, hash) {
        // Store hash in your password DB.
    });
});

And technique 2 (auto-gen a salt and hash):

bcrypt.hash(myPlaintextPassword, saltRounds, function(err, hash) {
    // Store hash in your password DB.
});

Note that both techniques achieve the same end-result…

If they do, why do we need to add extra lines of code?
Is it just esthetical preference? Or is there any practical reason?

Thank you!

1 thought on “Is there a practical difference between generate bcrypt salt and hash on separate function calls or auto-gen a salt and hash?”

  1. It’s a common implementation in a lot of libraries where they want to use the more tedious version.

    • they insist that you have to pass in everything required to run the function
    • and they abstract the details of passing in salt and cost and versioning away in a salt string

    I believe the method signature should be:

    bcrypt.HashPassword("hunter2"); //using a default cost
    
    bcrypt.HashPassword("hunter2", 15); //if we want to force a cost
    

    But nearly every other bcrypt library does something like:

    String salt = bcrypt.GenerateSalt(); //using a default cost
    bcrypt.HashPassword("hunter2", salt);
    
    String salt = bcrypt.GenerateSalt(15); //if we want to for a cost
    bcrypt.HashPassword("hunter2", salt);
    

    Because then what happens internally when they go to verify a hash, they extract the saved salt string from the stored hash:

    String salt = GetSaltStringFromSavedHash(savedHash);
    bcrypt.HashPassword("hunter2", salt);  
    

    And so they just love this symmetry of using HashPassword in the same way for both calls.

    I disagree that any of this salt should be exposed to the user – even if it designed to be an opaque blob (i.e. $2b$15$aXN0aWxsbG92ZXlvdWtn...).

    I think it should be:

    HashPassword(password);
    HashPassword(password, costFactor);
    

    But that’s just me; and i’m the only one.

    Reply

Leave a Comment