pejhancctv/utils/hash.go

66 lines
1.4 KiB
Go

package utils
import (
"crypto/rand"
"encoding/base64"
"fmt"
"golang.org/x/crypto/argon2"
)
type params struct {
memory uint32
iterations uint32
parallelism uint8
saltLength uint32
keyLength uint32
}
func HashPW(password string) (string, error) {
// Establish the parameters to use for Argon2.
p := &params{
memory: 128 * 1024,
iterations: 3,
parallelism: 2,
saltLength: 16,
keyLength: 32,
}
// Pass the plaintext password and parameters to our generateFromPassword
// helper function.
hash, err := generateFromPassword(password, p)
if err != nil {
return "", err
}
return hash, nil
}
func generateFromPassword(password string, p *params) (encodedHash string, err error) {
salt, err := generateRandomBytes(p.saltLength)
if err != nil {
return "", err
}
hash := argon2.IDKey([]byte(password), salt, p.iterations, p.memory, p.parallelism, p.keyLength)
// Base64 encode the salt and hashed password.
b64Salt := base64.RawStdEncoding.EncodeToString(salt)
b64Hash := base64.RawStdEncoding.EncodeToString(hash)
// Return a string using the standard encoded hash representation.
encodedHash = fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", argon2.Version, p.memory, p.iterations, p.parallelism, b64Salt, b64Hash)
return encodedHash, nil
}
func generateRandomBytes(n uint32) ([]byte, error) {
b := make([]byte, n)
_, err := rand.Read(b)
if err != nil {
return nil, err
}
return b, nil
}