authelia/internal/commands/hash.go

119 lines
4.5 KiB
Go
Raw Normal View History

package commands
import (
"fmt"
"github.com/simia-tech/crypt"
"github.com/spf13/cobra"
"github.com/authelia/authelia/v4/internal/authentication"
"github.com/authelia/authelia/v4/internal/configuration"
"github.com/authelia/authelia/v4/internal/configuration/schema"
"github.com/authelia/authelia/v4/internal/configuration/validator"
)
// NewHashPasswordCmd returns a new Hash Password Cmd.
func NewHashPasswordCmd() (cmd *cobra.Command) {
cmd = &cobra.Command{
Use: "hash-password [flags] -- <password>",
Short: "Hash a password to be used in file-based users database. Default algorithm is argon2id.",
Args: cobra.MinimumNArgs(1),
RunE: cmdHashPasswordRunE,
}
cmd.Flags().BoolP("sha512", "z", false, fmt.Sprintf("use sha512 as the algorithm (changes iterations to %d, change with -i)", schema.DefaultPasswordSHA512Configuration.Iterations))
cmd.Flags().IntP("iterations", "i", schema.DefaultPasswordConfiguration.Iterations, "set the number of hashing iterations")
cmd.Flags().StringP("salt", "s", "", "set the salt string")
cmd.Flags().IntP("memory", "m", schema.DefaultPasswordConfiguration.Memory, "[argon2id] set the amount of memory param (in MB)")
cmd.Flags().IntP("parallelism", "p", schema.DefaultPasswordConfiguration.Parallelism, "[argon2id] set the parallelism param")
cmd.Flags().IntP("key-length", "k", schema.DefaultPasswordConfiguration.KeyLength, "[argon2id] set the key length param")
cmd.Flags().IntP("salt-length", "l", schema.DefaultPasswordConfiguration.SaltLength, "set the auto-generated salt length")
cmd.Flags().StringSliceP("config", "c", []string{}, "Configuration files")
return cmd
[FEATURE] Support Argon2id password hasing and improved entropy (#679) * [FEATURE] Support Argon2id Passwords - Updated go module github.com/simia-tech/crypt - Added Argon2id support for file based authentication backend - Made it the default method - Made it so backwards compatibility with SHA512 exists - Force seeding of the random string generator used for salts to ensure they are all different - Added command params to the authelia hash-password command - Automatically remove {CRYPT} from hashes as they are updated - Automatically change hashes when they are updated to the configured algorithm - Made the hashing algorithm parameters completely configurable - Added reasonably comprehensive test suites - Updated docs - Updated config template * Adjust error output * Fix unit test * Add unit tests and argon2 version check * Fix new unit tests * Update docs, added tests * Implement configurable values and more comprehensive testing * Added cmd params to hash_password, updated docs, misc fixes * More detailed error for cmd, fixed a typo * Fixed cmd flag error, minor refactoring * Requested Changes and Minor refactoring * Increase entropy * Update docs for entropy changes * Refactor to reduce nesting and easier code maintenance * Cleanup Errors (uniformity for the function call) * Check salt length, fix docs * Add Base64 string validation for argon2id * Cleanup and Finalization - Moved RandomString function from ./internal/authentication/password_hash.go to ./internal/utils/strings.go - Added SplitStringToArrayOfStrings func that splits strings into an array with a fixed max string len - Fixed an error in validator that would allow a zero salt length - Added a test to verify the upstream crypt module supports our defined random salt chars - Updated docs - Removed unused "HashingAlgorithm" string type * Update crypt go mod, support argon2id key length and major refactor * Config Template Update, Final Tests * Use schema defaults for hash-password cmd * Iterations check * Docs requested changes * Test Coverage, suggested edits * Wording edit * Doc changes * Default sanity changes * Default sanity changes - docs * CI Sanity changes * Memory in MB
2020-03-06 08:38:02 +07:00
}
func cmdHashPasswordRunE(cmd *cobra.Command, args []string) (err error) {
salt, _ := cmd.Flags().GetString("salt")
sha512, _ := cmd.Flags().GetBool("sha512")
configs, _ := cmd.Flags().GetStringSlice("config")
mapDefaults := map[string]interface{}{
"authentication_backend.file.password.algorithm": schema.DefaultPasswordConfiguration.Algorithm,
"authentication_backend.file.password.iterations": schema.DefaultPasswordConfiguration.Iterations,
"authentication_backend.file.password.key_length": schema.DefaultPasswordConfiguration.KeyLength,
"authentication_backend.file.password.salt_length": schema.DefaultPasswordConfiguration.SaltLength,
"authentication_backend.file.password.parallelism": schema.DefaultPasswordConfiguration.Parallelism,
"authentication_backend.file.password.memory": schema.DefaultPasswordConfiguration.Memory,
}
if sha512 {
mapDefaults["authentication_backend.file.password.algorithm"] = schema.DefaultPasswordSHA512Configuration.Algorithm
mapDefaults["authentication_backend.file.password.iterations"] = schema.DefaultPasswordSHA512Configuration.Iterations
mapDefaults["authentication_backend.file.password.salt_length"] = schema.DefaultPasswordSHA512Configuration.SaltLength
}
mapCLI := map[string]string{
"iterations": "authentication_backend.file.password.iterations",
"key-length": "authentication_backend.file.password.key_length",
"salt-length": "authentication_backend.file.password.salt_length",
"parallelism": "authentication_backend.file.password.parallelism",
"memory": "authentication_backend.file.password.memory",
}
sources := configuration.NewDefaultSourcesWithDefaults(configs,
configuration.DefaultEnvPrefix, configuration.DefaultEnvDelimiter,
configuration.NewMapSource(mapDefaults),
configuration.NewCommandLineSourceWithMapping(cmd.Flags(), mapCLI, false, false),
)
val := schema.NewStructValidator()
if _, config, err = configuration.Load(val, sources...); err != nil {
return fmt.Errorf("error occurred loading configuration: %w", err)
}
var (
hash string
algorithm authentication.CryptAlgo
)
[FEATURE] Support Argon2id password hasing and improved entropy (#679) * [FEATURE] Support Argon2id Passwords - Updated go module github.com/simia-tech/crypt - Added Argon2id support for file based authentication backend - Made it the default method - Made it so backwards compatibility with SHA512 exists - Force seeding of the random string generator used for salts to ensure they are all different - Added command params to the authelia hash-password command - Automatically remove {CRYPT} from hashes as they are updated - Automatically change hashes when they are updated to the configured algorithm - Made the hashing algorithm parameters completely configurable - Added reasonably comprehensive test suites - Updated docs - Updated config template * Adjust error output * Fix unit test * Add unit tests and argon2 version check * Fix new unit tests * Update docs, added tests * Implement configurable values and more comprehensive testing * Added cmd params to hash_password, updated docs, misc fixes * More detailed error for cmd, fixed a typo * Fixed cmd flag error, minor refactoring * Requested Changes and Minor refactoring * Increase entropy * Update docs for entropy changes * Refactor to reduce nesting and easier code maintenance * Cleanup Errors (uniformity for the function call) * Check salt length, fix docs * Add Base64 string validation for argon2id * Cleanup and Finalization - Moved RandomString function from ./internal/authentication/password_hash.go to ./internal/utils/strings.go - Added SplitStringToArrayOfStrings func that splits strings into an array with a fixed max string len - Fixed an error in validator that would allow a zero salt length - Added a test to verify the upstream crypt module supports our defined random salt chars - Updated docs - Removed unused "HashingAlgorithm" string type * Update crypt go mod, support argon2id key length and major refactor * Config Template Update, Final Tests * Use schema defaults for hash-password cmd * Iterations check * Docs requested changes * Test Coverage, suggested edits * Wording edit * Doc changes * Default sanity changes * Default sanity changes - docs * CI Sanity changes * Memory in MB
2020-03-06 08:38:02 +07:00
p := config.AuthenticationBackend.File.Password
switch p.Algorithm {
case "sha512":
algorithm = authentication.HashingAlgorithmSHA512
default:
algorithm = authentication.HashingAlgorithmArgon2id
}
validator.ValidatePasswordConfiguration(p, val)
errs := val.Errors()
if len(errs) != 0 {
for i, e := range errs {
if i == 0 {
err = e
continue
}
err = fmt.Errorf("%v, %w", err, e)
}
return fmt.Errorf("errors occurred validating the password configuration: %w", err)
}
if salt != "" {
salt = crypt.Base64Encoding.EncodeToString([]byte(salt))
}
if hash, err = authentication.HashPassword(args[0], salt, algorithm, p.Iterations, p.Memory*1024, p.Parallelism, p.KeyLength, p.SaltLength); err != nil {
return fmt.Errorf("error during password hashing: %w", err)
}
fmt.Printf("Password hash: %s\n", hash)
return nil
}