相当于golang中的盐和哈希

Here's an example of salting and hashing a given password in python.

import scrypt
import os

# Length of salt
PW_SALT_BYTES = 32
# Length of scrypt hash of passwords
PW_HASH_BYTES = 64
# test password
password = "hello"

salt = os.urandom(PW_SALT_BYTES).encode('hex')
# hash(password, salt, N=1 << 14, r=8, p=1, buflen=64)
hashed_password = scrypt.hash(str(password), salt.decode('hex'), buflen=PW_HASH_BYTES).encode('hex')
print(hashed_password)

Which would give us a hashed and salted string in return:-

4d1da45b401961fccb10e094ecd70ec79510f05483ca293d300bbd0024e35866ca39fe09fbc15f83a359431021a1ed9644f7d2b871b357e37a186300877edb18

How would I implement this 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
", hash)
}

It looks like now Go has scrypt in official library. Its subrepository x/crypto among many other crypto functions has an scrypt.

Here is an example of how you can use it:

package main

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

func main(){
    salt := []byte("asdfasdf")
    dk, err := scrypt.Key([]byte("some password"), salt, 16384, 8, 1, 32)

    fmt.Println(dk)
    fmt.Println(err)
}

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
}