func Validate(password string, hash string) (bool, error) {
	params, salt, key, err := unpackHash(hash)
	if err != nil {
		return false, err
	}
	otherKey := argon2.Key([]byte(password), salt, params.Iterations, params.Memory, params.Parallelism, params.KeyLen)
	keyLen := int32(len(key))
	otherKeyLen := int32(len(otherKey))
	if subtle.ConstantTimeEq(keyLen, otherKeyLen) == 0 {
		return false, nil
	}
	if subtle.ConstantTimeCompare(key, otherKey) == 1 {
		return true, nil
	}
	return false, nil
}
Validate unpacks the parameters from the hash, computes the hash of the given
password with these parameters and performs a constant time comparison between
both hashes.
package argon2i
import (
	"crypto/rand"
	"crypto/subtle"
	"encoding/base64"
	"fmt"
	"strings"
	"golang.org/x/crypto/argon2"
)
var (
	ErrInvalidHash = fmt.Errorf("argon2i: invalid hash format")
	ErrVersionIncompatible = fmt.Errorf("argon2i: incompatible version")
	Prefix = "{ARGON2I}"
)
var DefaultParams = &Params{
	Memory:      256 * 1024,
	Iterations:  4,
	Parallelism: 4,
	SaltLen:     32,
	KeyLen:      32,
}
type Params struct {
	Memory      uint32
	Iterations  uint32
	Parallelism uint8
	SaltLen     uint32
	KeyLen      uint32
}
func Generate(password string, saltLen uint32) (string, error) {
	params := DefaultParams
	if saltLen > 0 {
		params.SaltLen = saltLen
	}
	salt := make([]byte, params.SaltLen)
	_, err := rand.Read(salt)
	if err != nil {
		return "", err
	}
	hash := argon2.Key([]byte(password), salt, params.Iterations, params.Memory, params.Parallelism, params.KeyLen)
	b64hash := base64.RawStdEncoding.EncodeToString(hash)
	b64salt := base64.RawStdEncoding.EncodeToString(salt)
	return fmt.Sprintf(Prefix+"$argon2i$v=%d$m=%d,t=%d,p=%d$%s$%s", argon2.Version, params.Memory, params.Iterations, params.Parallelism, b64salt, b64hash), nil
}