mirror of
https://github.com/kopia/kopia.git
synced 2026-03-11 18:56:28 -04:00
Code movement and simplification, no functional changes. Objectives: - Allow callers specifying the needed key (or hash) size, instead of hard-coding it in the registered PBK derivers. Conceptually, the caller needs to specify the key size, since that is a requirement of the (encryption) algorithm being used in the caller. Now, the code changes here do not result in any functional changes since the key size is always 32 bytes. - Remove a global definition for the default PB key deriver to use. Instead, each of the 3 use case sets the default value. Changes: - `crypto.DeriveKeyFromPassword` now takes a key size. - Adds new constants for the key sizes at the callers. - Removes the global `crypto.MasterKeySize` const. - Removes the global `crypto.DefaultKeyDerivationAlgorithm` const. - Adds const for the default derivation algorithms for each use case. - Adds a const for the salt length in the `internal/user` package, to ensure the same salt length is used in both hash versions. - Unexports various functions, variables and constants in the `internal/crypto` & `internal/user` packages. - Renames various constants for consistency. - Removes unused functions and symbols. - Renames files to be consistent and better reflect the structure of the code. - Adds a couple of tests to ensure the const values are in sync and supported. - Fixes a couple of typos Followups to: - #3725 - #3770 - #3779 - #3799 - #3816 The individual commits show the code transformations to simplify the review of the changes.
93 lines
2.8 KiB
Go
93 lines
2.8 KiB
Go
package user
|
|
|
|
import (
|
|
"math/rand"
|
|
|
|
"github.com/kopia/kopia/repo/manifest"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
const (
|
|
// ScryptHashVersion is the version representation of the scrypt algorithm.
|
|
ScryptHashVersion = 1
|
|
// scryptHashAlgorithm is the scrypt password hashing algorithm. This must match crypto.ScryptAlgorithm.
|
|
scryptHashAlgorithm = "scrypt-65536-8-1"
|
|
|
|
// Pbkdf2HashVersion is the version representation of the pbkdf2 algorithm.
|
|
Pbkdf2HashVersion = 2
|
|
// pbkdf2HashAlgorithm is the pbkdf2 password hashing algorithm. This must match crypto.Pbkdf2Algorithm.
|
|
pbkdf2HashAlgorithm = "pbkdf2-sha256-600000"
|
|
|
|
passwordHashLength = 32
|
|
passwordHashSaltLength = 32
|
|
)
|
|
|
|
// Profile describes information about a single user.
|
|
type Profile struct {
|
|
ManifestID manifest.ID `json:"-"`
|
|
|
|
Username string `json:"username"`
|
|
PasswordHashVersion int `json:"passwordHashVersion,omitempty"`
|
|
PasswordHash []byte `json:"passwordHash"`
|
|
}
|
|
|
|
// SetPassword changes the password for a user profile.
|
|
func (p *Profile) SetPassword(password string) error {
|
|
return p.setPassword(password)
|
|
}
|
|
|
|
// IsValidPassword determines whether the password is valid for a given user.
|
|
func (p *Profile) IsValidPassword(password string) bool {
|
|
var invalidProfile bool
|
|
|
|
var passwordHashAlgorithm string
|
|
|
|
var err error
|
|
|
|
if p == nil {
|
|
invalidProfile = true
|
|
} else {
|
|
passwordHashAlgorithm, err = getPasswordHashAlgorithm(p.PasswordHashVersion)
|
|
if err != nil {
|
|
invalidProfile = true
|
|
}
|
|
}
|
|
|
|
if invalidProfile {
|
|
algorithms := PasswordHashingAlgorithms()
|
|
// if the user profile is invalid, either a non-existing user name or password
|
|
// hash version, then return false but use the same amount of time as when we
|
|
// compare against valid user to avoid revealing whether the user account exists.
|
|
isValidPassword(password, dummyHashThatNeverMatchesAnyPassword, algorithms[rand.Intn(len(algorithms))]) //nolint:gosec
|
|
|
|
return false
|
|
}
|
|
|
|
return isValidPassword(password, p.PasswordHash, passwordHashAlgorithm)
|
|
}
|
|
|
|
// getPasswordHashAlgorithm returns the password hash algorithm given a version.
|
|
func getPasswordHashAlgorithm(passwordHashVersion int) (string, error) {
|
|
switch passwordHashVersion {
|
|
case ScryptHashVersion:
|
|
return scryptHashAlgorithm, nil
|
|
case Pbkdf2HashVersion:
|
|
return pbkdf2HashAlgorithm, nil
|
|
default:
|
|
return "", errors.Errorf("unsupported hash version (%d)", passwordHashVersion)
|
|
}
|
|
}
|
|
|
|
// GetPasswordHashVersion returns the password hash version given an algorithm.
|
|
func GetPasswordHashVersion(passwordHashAlgorithm string) (int, error) {
|
|
switch passwordHashAlgorithm {
|
|
case scryptHashAlgorithm:
|
|
return ScryptHashVersion, nil
|
|
case pbkdf2HashAlgorithm:
|
|
return Pbkdf2HashVersion, nil
|
|
default:
|
|
return 0, errors.Errorf("unsupported hash algorithm (%s)", passwordHashAlgorithm)
|
|
}
|
|
}
|