Home About Me

Password Hashing in Go with bcrypt

Passwords should not be stored in plain text. In Go, the bcrypt package from golang.org/x/crypto provides a compact way to create a password hash and compare a later login attempt with the stored hash.

Install

go get golang.org/x/crypto/bcrypt

# If the dependency package fails to install, use a proxy
export GOPROXY=https://goproxy.io,direct
or
export GOPROXY=https://goproxy.cn,direct

Create a hash

When a user registers or changes a password, take the password they submitted and pass it to bcrypt.GenerateFromPassword. The returned value is a byte slice; convert it to a string before saving it to the database.

// 1. Get the password passed in by the user and convert it to a byte slice
originPwd := []byte("password") // the actual password value passed by the user

// 2. Call bcrypt.GenerateFromPassword to generate the hashed string
hashPwd, _ := bcrypt.GenerateFromPassword(originPwd, bcrypt.DefaultCost)

// 3. At this point hashPwd is a byte slice; the actual hashed string needs to be converted with string
string(hashPwd) // this hashed string can be saved to the database and used for password matching verification

Verify a password

At login, read the stored hash and convert it to a byte slice. Convert the password entered by the user in the same way, then call bcrypt.CompareHashAndPassword. If the function returns no error, the password matches.

// 1. Convert the hashed string from the database to a byte slice
// $2a$10$oxOlhX8ju5eIwHZkjTwMX.4q64EhyjLtX2m32b2V3CP8yeqzQNVHa
byteHashPwd := []byte("$2sxxx....") // the actual hashed string

// 2. Call bcrypt.CompareHashAndPassword to verify whether the password matches
// The first argument is the hashed string converted to a byte slice, and the second is the user's input password converted to a byte slice
err := bcrypt.CompareHashAndPassword(byteHashPwd, originPwd)
// If there is no error, the password matches
if err != nil {
    log.Println(err)
    return false
}

This comparison approach also works with password hashes generated by Laravel.