code.gitea.io/gitea@v1.19.3/modules/auth/password/hash/scrypt.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/scrypt"
    13  )
    14  
    15  func init() {
    16  	MustRegister("scrypt", NewScryptHasher)
    17  }
    18  
    19  // ScryptHasher implements PasswordHasher
    20  // and uses the scrypt key derivation function.
    21  type ScryptHasher struct {
    22  	n, r, p, keyLen int
    23  }
    24  
    25  // HashWithSaltBytes a provided password and salt
    26  func (hasher *ScryptHasher) HashWithSaltBytes(password string, salt []byte) string {
    27  	if hasher == nil {
    28  		return ""
    29  	}
    30  	hashedPassword, _ := scrypt.Key([]byte(password), salt, hasher.n, hasher.r, hasher.p, hasher.keyLen)
    31  	return hex.EncodeToString(hashedPassword)
    32  }
    33  
    34  // NewScryptHasher is a factory method to create an ScryptHasher
    35  // The provided config should be either empty or of the form:
    36  // "<n>$<r>$<p>$<keyLen>", where <x> is the string representation
    37  // of an integer
    38  func NewScryptHasher(config string) *ScryptHasher {
    39  	// This matches the original configuration for `scrypt` prior to storing hash parameters
    40  	// in the database.
    41  	// THESE VALUES MUST NOT BE CHANGED OR BACKWARDS COMPATIBILITY WILL BREAK
    42  	hasher := &ScryptHasher{
    43  		n:      1 << 16,
    44  		r:      16,
    45  		p:      2, // 2 passes through memory - this default config will use 128MiB in total.
    46  		keyLen: 50,
    47  	}
    48  
    49  	if config == "" {
    50  		return hasher
    51  	}
    52  
    53  	vals := strings.SplitN(config, "$", 4)
    54  	if len(vals) != 4 {
    55  		log.Error("invalid scrypt hash spec %s", config)
    56  		return nil
    57  	}
    58  	var err error
    59  	hasher.n, err = parseIntParam(vals[0], "n", "scrypt", config, nil)
    60  	hasher.r, err = parseIntParam(vals[1], "r", "scrypt", config, err)
    61  	hasher.p, err = parseIntParam(vals[2], "p", "scrypt", config, err)
    62  	hasher.keyLen, err = parseIntParam(vals[3], "keyLen", "scrypt", config, err)
    63  	if err != nil {
    64  		return nil
    65  	}
    66  	return hasher
    67  }