Skip to content

Instantly share code, notes, and snippets.

@ciehanski
Last active June 13, 2020 01:30
Show Gist options
  • Save ciehanski/ed4a247fe82e00a9c23ab8f72ddd723e to your computer and use it in GitHub Desktop.
Save ciehanski/ed4a247fe82e00a9c23ab8f72ddd723e to your computer and use it in GitHub Desktop.
Using argon2 in Golang
func hashPassword(password string) (string, error) {
salt := make([]byte, argonSaltLen)
_, err := rand.Read(salt)
if err != nil {
return "", err
}
passwordHash := argon2.IDKey([]byte(password), salt, argonTime, argonMemory, argonThreads, argonKeyLen)
// Base64 encode the salt and hashed password
b64Salt := base64.RawStdEncoding.EncodeToString(salt)
b64Hash := base64.RawStdEncoding.EncodeToString(passwordHash)
// Return a string using the standard encoded hash representation
return fmt.Sprintf("$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", argon2.Version,
argonMemory, argonTime, argonThreads, b64Salt, b64Hash), nil
}
func comparePasswordHash(expectedPassword, providedPassword string) (bool, error) {
vals := strings.Split(expectedPassword, "$")
if len(vals) != 6 {
return false, errors.New("invalid hash")
}
var version int
_, err := fmt.Sscanf(vals[2], "v=%d", &version)
if err != nil {
return false, err
}
if version != argon2.Version {
return false, errors.New("wrong argon version")
}
var mem, iter uint32
var thread uint8
_, err = fmt.Sscanf(vals[3], "m=%d,t=%d,p=%d", &mem, &iter, &thread)
if err != nil {
return false, err
}
salt, err := base64.RawStdEncoding.DecodeString(vals[4])
if err != nil {
return false, err
}
actualPasswordHash, err := base64.RawStdEncoding.DecodeString(vals[5])
if err != nil {
return false, err
}
providedPasswordHash := argon2.IDKey([]byte(providedPassword), salt, iter, mem, thread,
uint32(len(actualPasswordHash)))
return subtle.ConstantTimeCompare(actualPasswordHash, providedPasswordHash) == 1, nil
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment