equivalent salt and hash in golang

Go doesn't have scrypt in the standard library but there is an "official" implementation in the go.crypto repo.

import (
    "crypto/rand"
    "fmt"
    "io"
    "log"

    "code.google.com/p/go.crypto/scrypt"
)

const (
    PW_SALT_BYTES = 32
    PW_HASH_BYTES = 64

    password = "hello"
)

func main() {
    salt := make([]byte, PW_SALT_BYTES)
    _, err := io.ReadFull(rand.Reader, salt)
    if err != nil {
        log.Fatal(err)
    }

    hash, err := scrypt.Key([]byte(password), salt, 1<<14, 8, 1, PW_HASH_BYTES)
    if err != nil {
        log.Fatal(err)
    }

    fmt.Printf("%x\n", hash)
}

Rather than using scrypt, a great library for securely hashing passwords with random salts in Golang is golang.org/x/crypto/bcrypt, as mentioned in the following answer:

Bcrypt password hashing in Golang (compatible with Node.js)?

A couple benefits of using bcrypt instead of scrypt:

  1. The salt is automatically (and randomly) generated upon hashing a password, so that you don't have to worry about salt generation.
  2. When storing hashed passwords in a database, you no longer have to worry about storing the salt for each password hash as well.
  3. The syntax is simplified for hashing and checking passwords.
  4. The hash produced by bcrypt includes the bcrypt version, cost, salt and cipher, not only the cipher.

Here's an example of using bcrypt taken from the above answer:

package main

import (
    "golang.org/x/crypto/bcrypt"
    "fmt"
)

func main() {
    password := []byte("MyDarkSecret")

    // Hashing the password with the default cost of 10
    hashedPassword, err := bcrypt.GenerateFromPassword(password, bcrypt.DefaultCost)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(hashedPassword))

    // Comparing the password with the hash
    err = bcrypt.CompareHashAndPassword(hashedPassword, password)
    fmt.Println(err) // nil means it is a match
}

Tags:

Go