code.gitea.io/gitea@v1.19.3/modules/auth/password/hash/argon2.go (about) 1 // Copyright 2023 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package hash 5 6 import ( 7 "encoding/hex" 8 "strings" 9 10 "code.gitea.io/gitea/modules/log" 11 12 "golang.org/x/crypto/argon2" 13 ) 14 15 func init() { 16 MustRegister("argon2", NewArgon2Hasher) 17 } 18 19 // Argon2Hasher implements PasswordHasher 20 // and uses the Argon2 key derivation function, hybrant variant 21 type Argon2Hasher struct { 22 time uint32 23 memory uint32 24 threads uint8 25 keyLen uint32 26 } 27 28 // HashWithSaltBytes a provided password and salt 29 func (hasher *Argon2Hasher) HashWithSaltBytes(password string, salt []byte) string { 30 if hasher == nil { 31 return "" 32 } 33 return hex.EncodeToString(argon2.IDKey([]byte(password), salt, hasher.time, hasher.memory, hasher.threads, hasher.keyLen)) 34 } 35 36 // NewArgon2Hasher is a factory method to create an Argon2Hasher 37 // The provided config should be either empty or of the form: 38 // "<time>$<memory>$<threads>$<keyLen>", where <x> is the string representation 39 // of an integer 40 func NewArgon2Hasher(config string) *Argon2Hasher { 41 // This default configuration uses the following parameters: 42 // time=2, memory=64*1024, threads=8, keyLen=50. 43 // It will make two passes through the memory, using 64MiB in total. 44 // This matches the original configuration for `argon2` prior to storing hash parameters 45 // in the database. 46 // THESE VALUES MUST NOT BE CHANGED OR BACKWARDS COMPATIBILITY WILL BREAK 47 hasher := &Argon2Hasher{ 48 time: 2, 49 memory: 1 << 16, 50 threads: 8, 51 keyLen: 50, 52 } 53 54 if config == "" { 55 return hasher 56 } 57 58 vals := strings.SplitN(config, "$", 4) 59 if len(vals) != 4 { 60 log.Error("invalid argon2 hash spec %s", config) 61 return nil 62 } 63 64 parsed, err := parseUIntParam(vals[0], "time", "argon2", config, nil) 65 hasher.time = uint32(parsed) 66 67 parsed, err = parseUIntParam(vals[1], "memory", "argon2", config, err) 68 hasher.memory = uint32(parsed) 69 70 parsed, err = parseUIntParam(vals[2], "threads", "argon2", config, err) 71 hasher.threads = uint8(parsed) 72 73 parsed, err = parseUIntParam(vals[3], "keyLen", "argon2", config, err) 74 hasher.keyLen = uint32(parsed) 75 if err != nil { 76 return nil 77 } 78 79 return hasher 80 }