DEV Community

Cover image for How to Hash Passwords Securely Using SHA-256 in Go
omulo samuel okoth
omulo samuel okoth

Posted on

How to Hash Passwords Securely Using SHA-256 in Go

Introduction

Storing passwords securely is crucial to protecting user data. Storing passwords in plain text is a significant security risk, but hashing can mitigate this threat. In this article, we’ll explore how to securely hash passwords using SHA-256 in Go. While bcrypt and Argon2 are generally recommended for password hashing due to their added security features, we can enhance the security of SHA-256 by incorporating a unique salt and multiple iterations.
Why SHA-256 for Password Hashing?
SHA-256 produces a unique, 256-bit fixed-length hash, effectively transforming any password into a consistent, secure format. However, due to its speed, SHA-256 can be vulnerable to brute-force attacks. Therefore, combining SHA-256 with techniques like salting and iteration can significantly improve its security.

Importing necessary packages

First, let's import the necessary packages for cryptographic hashing and encoding:

package main

   import (
    "crypto/sha256"
    "encoding/hex"
    "fmt"
   )
Enter fullscreen mode Exit fullscreen mode

Hash the Password

Here’s a basic SHA-256 function that hashes a password:

func hash password(password string) string {
    hasher := sha256.New()
    hasher.Write([]byte(password))
    return hex.EncodeToString(hasher.Sum(nil))
}

Enter fullscreen mode Exit fullscreen mode

Add Salt for Extra Security

A salt is a unique random string added to each password. It ensures that even if two users have the same password, their hashes will be different, preventing rainbow table attacks.

func hashPasswordWithSalt(password, salt string) string {
    hasher := sha256.New()
    hasher.Write([]byte(salt + password))
    return hex.EncodeToString(hasher.Sum(nil))
}
Enter fullscreen mode Exit fullscreen mode

Note:

It's essential to generate a unique salt for each user's password and store it securely in the database.
Add Iterations for More Security
Adding multiple iterations to the hashing process slows down brute-force attacks by increasing the time required to compute the hash.

Here's how to implement this:

func hashPasswordWithSaltAndIterations(password, salt string, iterations int) string {
    hash := salt + password
    for i := 0; i < iterations; i++ {
        hasher := sha256.New()
        hasher.Write([]byte(hash))
        hash = hex.EncodeToString(hasher.Sum(nil))
    }
    return hash
}
Enter fullscreen mode Exit fullscreen mode

Example Usage
Let’s see how these techniques work in practice. The following example hashes a password with both a salt and iterations:

func main() {
    password := "MySecurePassword"
    salt:= "unique salt" // Generate a unique, random salt for each user
    iterations := 1000    // Choose a safe iteration count
    hashed password := hashPasswordWithSaltAndIterations(password, salt, iterations)
    fmt.Println("Hashed Password:", hashedpassword)
}
Enter fullscreen mode Exit fullscreen mode

Key Points to Remember

Generate Secure Salts: Use Go’s crypto/rand to generate secure, unique salts for each user.
Store Salt and Hash: Save both the salt and the hashed password in your database. The salt should never be kept secret but must be unique to each user.
Consider bcrypt or Argon2: For even better security, consider using bcrypt or Argon2 for password hashing, especially in high-security systems. These algorithms are specifically designed for secure password storage.

Conclusion

While SHA-256 isn't the ideal choice for password hashing in high-security systems, combining it with salting and multiple iterations can significantly strengthen password protection. This approach helps deter brute-force attacks and keeps your users' data safer. For applications that require the highest security, consider using algorithms like bcrypt or Argon2 instead.

Top comments (0)