authelia/internal/commands/hash.go
James Elliott 26369fff3d
[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 12:38:02 +11:00

55 lines
2.4 KiB
Go

package commands
import (
"fmt"
"github.com/authelia/authelia/internal/authentication"
"github.com/authelia/authelia/internal/configuration/schema"
"github.com/spf13/cobra"
)
func init() {
HashPasswordCmd.Flags().BoolP("sha512", "z", false, fmt.Sprintf("use sha512 as the algorithm (changes iterations to %d, change with -i)", schema.DefaultPasswordOptionsSHA512Configuration.Iterations))
HashPasswordCmd.Flags().IntP("iterations", "i", schema.DefaultPasswordOptionsConfiguration.Iterations, "set the number of hashing iterations")
HashPasswordCmd.Flags().StringP("salt", "s", "", "set the salt string")
HashPasswordCmd.Flags().IntP("memory", "m", schema.DefaultPasswordOptionsConfiguration.Memory, "[argon2id] set the amount of memory param (in MB)")
HashPasswordCmd.Flags().IntP("parallelism", "p", schema.DefaultPasswordOptionsConfiguration.Parallelism, "[argon2id] set the parallelism param")
HashPasswordCmd.Flags().IntP("key-length", "k", schema.DefaultPasswordOptionsConfiguration.KeyLength, "[argon2id] set the key length param")
HashPasswordCmd.Flags().IntP("salt-length", "l", schema.DefaultPasswordOptionsConfiguration.SaltLength, "set the auto-generated salt length")
}
var HashPasswordCmd = &cobra.Command{
Use: "hash-password [password]",
Short: "Hash a password to be used in file-based users database. Default algorithm is argon2id.",
Run: func(cobraCmd *cobra.Command, args []string) {
sha512, _ := cobraCmd.Flags().GetBool("sha512")
iterations, _ := cobraCmd.Flags().GetInt("iterations")
salt, _ := cobraCmd.Flags().GetString("salt")
keyLength, _ := cobraCmd.Flags().GetInt("key-length")
saltLength, _ := cobraCmd.Flags().GetInt("salt-length")
memory, _ := cobraCmd.Flags().GetInt("memory")
parallelism, _ := cobraCmd.Flags().GetInt("parallelism")
var err error
var hash string
var algorithm string
if sha512 {
if iterations == schema.DefaultPasswordOptionsConfiguration.Iterations {
iterations = schema.DefaultPasswordOptionsSHA512Configuration.Iterations
}
algorithm = authentication.HashingAlgorithmSHA512
} else {
algorithm = authentication.HashingAlgorithmArgon2id
}
hash, err = authentication.HashPassword(args[0], salt, algorithm, iterations, memory*1024, parallelism, keyLength, saltLength)
if err != nil {
fmt.Println(fmt.Sprintf("Error occured during hashing: %s", err))
} else {
fmt.Println(fmt.Sprintf("Password hash: %s", hash))
}
},
Args: cobra.MinimumNArgs(1),
}