Password Encoding

I am taking up a project that another developer had written many years ago in PHP. I want to write a Go app that can perform the same function but am confused with a few things.

Here is the PHP code I’m trying to recreate in Go:

$salt = substr($correctHash, 0, 64); //get the salt from the front of the current hash  from the db                                                                                                              
$validHash = substr($correctHash, 64, 64); //the SHA256                                                                                                                                                                                                                                                                                                                                 
$testHash = hash("sha256", $salt . $password); //create new hash to compare to original

Note: $password is the text phrase sent by user to be validated, $correctHash is the hash stored in our database to compare against.

My first question is that it appears he stored the salt along with the hashed value of the password originally. He strips off the salt from the front of the hash stored in the db and then uses the first 64 characters to salt the new call for what the user just passed in. Is this the proper way to deal with the salt as it would appear to make the salt pointless?

Secondly, I’m having a hard time figuring out how to perform sha256 with a salt in order to get a hash key in Go. Can anyone point me to an example of how to do this?

Thanks,

G

1 Like

Go standard library have a package for sha256.

1 Like

Thanks and yes, I looked at that already but don’t see how you pass in a salt to that function.

1 Like

Hi @cybercrypt13,

Just a quick comment to say that it’s also a good idea for passwords to use something stronger than sha256, such as bcrypt that also handles the salting part of it for you.

Here’s an example:

https://gowebexamples.com/password-hashing/

2 Likes

Thanks and was already looking at it but before I could go that route I’d have to convert the current password hashes over during login process. This could easily be done but before I swap it I need to be able to verify the password they just gave me was correct based on the old salt and hash.

1 Like

Hi @cybercrypt13,

Based on your example of fetching the salt, I’m guessing the salt was prefixed after hashing the password, which if it’s the case, you can just use something like this:

https://play.golang.org/p/u8ua3R0bYng

Also, yes, not the best idea to just add the salt to the front of a hash. I think it’s more common to hash with the salt added and then store the original salt in a database somewhere and fetch when doing comparisons (That’s my understanding of it anyway).

1 Like

Thanks but I don’t see what you’re doing with the salt. You pass it into the function only to prepend it to the hash. But the hash is created with the salt.

Note the 3rd line of my example code where in php you generate the hash by passing into the hash function the password you want to hash plus a salt.

In php we get the original salt by doing this:
$salt = bin2hex(random_bytes(32));

1 Like

Hi @cybercrypt13,

Sorry, I misread the original 3rd line in your example!

Anyway, in that case, are you not retrieving the salt from the hashed password from the database separately? I didn’t think you could just strip off characters from a salted hash and “re-use” that for salting a new hash to compare the values.

$salt = substr($correctHash, 0, 64);

Is the part I’m referring to. What does correctHash contain? Is it the full salt stored in parts 0-64 and then 65 onwards in the actual hash? If so, that would make more sense to me :slight_smile:

For example, after the initial hashing for when saving a password, are you storing it somehow like this.

$salt = bin2hex(random_bytes(32)); // New salt
$newpass = hash("sha256", $salt . $password); // Create hash password

/* Store password somehow in users with the password set to salt + hash */

If this is the case, here’s a different example to handle that :slight_smile: :

https://play.golang.org/p/WVJJNwEmZl7

1 Like

Also now realizing that the salt was actual hashed, this is actual correct and is definitely not pointless.

It pretty much means that instead of hacker being able to use a rainbow table to match against all passwords without salts, they would have to take the salt for each single password (since every password has a unique salt) and generate new rainbow tables for each password based on that salt, and then do comparisons from that specific new rainbow table, which would be extremely timely and unfeasible. So even if they can crack one password, cracking all in a database would take a huge amount of time.

From an answer I found here explaining it better than I have probably (https://crypto.stackexchange.com/questions/51770/how-come-hash-salt-doesnt-make-a-hash-ineffective):

The salt is stored in plaintext next to the hash and the same salt is used when checking a password.

Its purpose is to slow down attackers who obtained a copy of the database:

  • They must attack each password on its own (they need to try each input for each hash instead of trying each input and comparing the output to all hashes at once).
  • They can’t make use of huge precomputed lookup tables (“rainbow tables”) since salting is essentially equivalent to giving each user their own hash function.

There is no need to keep the salt secret or store it more safely than the corresponding hash.

Thanks and yes that is correct. I finally got my head wrapped around the point of the salt yesterday. :slight_smile:

And the salt is just the first 64 bytes with the actual hash at the end. So we strip it off to reuse each time the user logs in to compare the new hash with the last 65 bytes stored at the end of the password field.

I’ll give your example a shot and see if I can get it to work.

Thanks again for all the help,

Worked perfectly, thanks for all your help

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.