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  }