2020-01-22 05:45:04 +07:00
package commands
import (
"fmt"
2020-05-14 12:55:03 +07:00
"github.com/simia-tech/crypt"
2020-04-05 19:37:21 +07:00
"github.com/spf13/cobra"
2021-08-11 08:04:35 +07:00
"github.com/authelia/authelia/v4/internal/authentication"
2021-09-16 07:20:42 +07:00
"github.com/authelia/authelia/v4/internal/configuration"
2021-08-11 08:04:35 +07:00
"github.com/authelia/authelia/v4/internal/configuration/schema"
2022-06-02 06:18:45 +07:00
"github.com/authelia/authelia/v4/internal/configuration/validator"
2020-01-22 05:45:04 +07:00
)
2021-08-03 16:55:21 +07:00
// NewHashPasswordCmd returns a new Hash Password Cmd.
func NewHashPasswordCmd ( ) ( cmd * cobra . Command ) {
cmd = & cobra . Command {
2022-06-02 06:18:45 +07:00
Use : "hash-password [flags] -- <password>" ,
2021-08-03 16:55:21 +07:00
Short : "Hash a password to be used in file-based users database. Default algorithm is argon2id." ,
Args : cobra . MinimumNArgs ( 1 ) ,
2022-06-02 06:18:45 +07:00
RunE : cmdHashPasswordRunE ,
2021-08-03 16:55:21 +07:00
}
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" )
2021-09-16 07:20:42 +07:00
cmd . Flags ( ) . StringSliceP ( "config" , "c" , [ ] string { } , "Configuration files" )
2021-08-03 16:55:21 +07:00
return cmd
2020-03-06 08:38:02 +07:00
}
2022-06-02 06:18:45 +07:00
func cmdHashPasswordRunE ( cmd * cobra . Command , args [ ] string ) ( err error ) {
2021-08-03 16:55:21 +07:00
salt , _ := cmd . Flags ( ) . GetString ( "salt" )
2022-06-02 06:18:45 +07:00
sha512 , _ := cmd . Flags ( ) . GetBool ( "sha512" )
2021-09-16 07:20:42 +07:00
configs , _ := cmd . Flags ( ) . GetStringSlice ( "config" )
2022-06-02 06:18:45 +07:00
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 ,
}
2021-09-16 07:20:42 +07:00
2022-06-02 06:18:45 +07:00
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
}
2021-09-16 07:20:42 +07:00
2022-06-02 06:18:45 +07:00
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 )
2021-09-16 07:20:42 +07:00
}
2021-08-03 16:55:21 +07:00
var (
hash string
algorithm authentication . CryptAlgo
)
2020-03-06 08:38:02 +07:00
2022-06-02 06:18:45 +07:00
p := config . AuthenticationBackend . File . Password
2021-08-03 16:55:21 +07:00
2022-06-02 06:18:45 +07:00
switch p . Algorithm {
case "sha512" :
2021-08-03 16:55:21 +07:00
algorithm = authentication . HashingAlgorithmSHA512
2022-06-02 06:18:45 +07:00
default :
2021-08-03 16:55:21 +07:00
algorithm = authentication . HashingAlgorithmArgon2id
}
2022-06-02 06:18:45 +07:00
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 )
}
2021-08-03 16:55:21 +07:00
if salt != "" {
salt = crypt . Base64Encoding . EncodeToString ( [ ] byte ( salt ) )
}
2022-06-02 06:18:45 +07:00
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 )
2021-08-03 16:55:21 +07:00
}
fmt . Printf ( "Password hash: %s\n" , hash )
2022-06-02 06:18:45 +07:00
return nil
2020-01-22 05:45:04 +07:00
}