Hi everyone, I am Hu Ge.
Recently, while handling user login functionality in a project, I encountered a “common issue”—how to securely store user passwords.
As a programmer who has been battling on the front line for years, I am very aware of how sensitive password storage is. Especially if the database is compromised, and password data is leaked in plaintext, it would be quite embarrassing.
Many simple encryption methods on the market, such as MD5, have been widely used, but they are not particularly reassuring in terms of security. So what should we do? This is where bcrypt comes into play.
Bcrypt is a password hashing algorithm specifically designed to store passwords in an encrypted form in the database. Compared to general hashing algorithms like MD5, bcrypt is more suitable for handling user passwords for a simple reason—it is not only more secure but also effectively prevents brute-force attacks.
Today, let’s talk about how to use bcrypt in Golang projects to implement password encryption and verification.
Why Choose Bcrypt?
First of all, why should we use bcrypt? From a security perspective, bcrypt is more suitable for encrypting passwords compared to algorithms like MD5 and SHA-1. This is because bcrypt introduces a random “salt” when generating hashes, and it supports setting a computation cost (Cost), meaning that each time a hash is generated, it is different, even if the original password is the same. This means that even if an attacker obtains the encrypted hash data, they cannot directly reverse-engineer the original password through brute-force cracking or pre-computed tables (like rainbow tables).
Moreover, the design philosophy of bcrypt is to make the computation time as long as possible, increasing the cost of brute-force cracking. For modern computers, this computation time does not affect performance, but for hackers, it is a significant obstacle.
Installing the Bcrypt Library
Using bcrypt in Go is very simple; first, you need to install this library:
go get -u golang.org/x/crypto/bcrypt
Then you can import this library into your project and start encrypting and verifying passwords.
Password Encryption
Let’s first look at how to encrypt user passwords using bcrypt. Here is a simple code example:
package main
import (
"fmt"
"golang.org/x/crypto/bcrypt"
)
func main() {
password := "123456" // Encrypt the password
hashedPassword, _ := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
fmt.Println(string(hashedPassword))
}
Here we call the bcrypt.GenerateFromPassword method, which takes two parameters: the first is the password to be encrypted, and the second is the encryption cost bcrypt.DefaultCost. The higher the cost value, the longer it takes to generate the hash, and of course, the security will also be higher. For most application scenarios, the default cost value bcrypt.DefaultCost is already secure enough.
It is worth noting that every time you run this code, the output of the encrypted result is different. Although the original password is the same, the bcrypt uses a random salt, so the generated hash will be different each time, which is key to preventing rainbow table attacks.
Password Verification
Now the question arises: since the hash values generated by bcrypt are different each time, how does the system know if the user-entered password is correct? Good question! In fact, bcrypt provides a very convenient method CompareHashAndPassword, which helps us verify whether the user-entered password matches the encrypted hash. Let’s look at the code example:
package main
import (
"fmt"
"golang.org/x/crypto/bcrypt"
)
func main() {
password := "123456"
hashedPassword := "$2a$10$EvdBpymvP7uDfI0TFRD6RO3YXLwQWUVYKMDqbWFloYCtyNXHCmbD2" // Validate if the password matches
err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
if err != nil {
fmt.Println("Password incorrect")
} else {
fmt.Println("Password matches")
}
}
In this code, we first provide an encrypted password hash (usually stored in the database), and then use the bcrypt.CompareHashAndPassword method to compare the user-entered password with the stored hash. If the match is successful, it returns nil; otherwise, it returns an error. Simple and direct, very convenient.
Encapsulating Utility Class
For common operations like password encryption and verification, we can completely encapsulate them into a utility class to make the code cleaner. For example, you can write it like this:
package utils
import "golang.org/x/crypto/bcrypt"
// Encrypt password
func GenerateFromPassword(password string) (string, error) {
hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
if err != nil {
return "", err
}
return string(hashedPassword), nil
}
// Verify password
func CompareHashAndPassword(hashedPassword string, password string) bool {
err := bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password))
return err == nil
}
With this encapsulation, you only need to call the GenerateFromPassword and CompareHashAndPassword methods when using it, greatly improving code reusability and readability. Moreover, if you need to adjust the encryption cost or other parameters in the future, you only need to modify them in the utility class, and there is no need to change the business logic.
My Experience with Bcrypt
In fact, the usage scenarios of bcrypt are very broad, especially in systems dealing with user authentication. We often need to consider how to minimize the risk of password leakage, and bcrypt is undoubtedly a good choice. By introducing random salt values, adjustable cost parameters, and generating different hash values each time, it can effectively enhance the security of passwords.
Of course, not every situation requires the use of bcrypt. For some non-sensitive data, faster algorithms like MD5 may be more suitable. But when it comes to sensitive information like passwords, I believe bcrypt is a very reliable choice.
Conclusion
In summary, bcrypt provides us with a simple yet powerful tool to handle password storage and verification securely. For programmers, it is not only easy to use but also strengthens your system against attacks.
I personally highly recommend using bcrypt in scenarios involving user passwords. I hope this article helps you understand its basic usage and assists you in practical development.
Currently, for students interested in programming and the workplace, you can contact me on WeChat:golang404, and I will add you to the “Programmer Group Chat”.
🔥Hu Ge’s Private Collection of Quality Recommendations🔥
The resources include “IDEA Video Tutorial”, “Most Comprehensive GO Interview Question Bank”, “Most Comprehensive Project Practice Source Code and Video”, and “Graduation Design System Source Code”, totaling up to650GB. All arefree to receive! Fully meet the learning needs of programmers at various stages!