mirror of
https://github.com/caddyserver/caddy.git
synced 2026-10-25 05:18:48 -04:00
feat: add bcrypt cost parameter to hash-password
This commit is contained in:
4 files changed
+17
-9
No files matched your search
@@ -234,7 +234,7 @@ func (c *Cache) makeRoom() {
|
||||
// we delete more than just 1 entry so that we don't have
|
||||
// to do this on every request; assuming the capacity of
|
||||
// the cache is on a long tail, we can save a lot of CPU
|
||||
// time by doing a whole bunch of deletions now and then
|
||||
// time by doing a whole bunch of deletions now, and then
|
||||
// we won't have to do them again for a while
|
||||
numToDelete := max(len(c.cache)/10, 1)
|
||||
for deleted := 0; deleted <= numToDelete; deleted++ {
|
||||
@@ -276,7 +276,7 @@ type Comparer interface {
|
||||
// features. A hasher also returns a fake hash which
|
||||
// can be used for timing side-channel mitigation.
|
||||
type Hasher interface {
|
||||
Hash(plaintext []byte) ([]byte, error)
|
||||
Hash(plaintext []byte, cost int) ([]byte, error)
|
||||
FakeHash() []byte
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,8 @@ func (Authentication) CaddyModule() caddy.ModuleInfo {
|
||||
}
|
||||
}
|
||||
|
||||
// Provision sets up a.
|
||||
// Provision sets up an Authentication module by initializing its logger,
|
||||
// loading and registering all configured authentication providers.
|
||||
func (a *Authentication) Provision(ctx caddy.Context) error {
|
||||
a.logger = ctx.Logger()
|
||||
a.Providers = make(map[string]Authenticator)
|
||||
@@ -120,7 +121,7 @@ type User struct {
|
||||
ID string
|
||||
|
||||
// Any other relevant data about this
|
||||
// user. Keys should be adhere to Caddy
|
||||
// user. Keys should be adhered to Caddy
|
||||
// conventions (snake_casing), as all
|
||||
// keys will be made available as
|
||||
// placeholders.
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
func init() {
|
||||
caddycmd.RegisterCommand(caddycmd.Command{
|
||||
Name: "hash-password",
|
||||
Usage: "[--plaintext <password>] [--algorithm <name>]",
|
||||
Usage: "[--plaintext <password>] [--algorithm <name>] [--cost <difficulty>]",
|
||||
Short: "Hashes a password and writes base64",
|
||||
Long: `
|
||||
Convenient way to hash a plaintext password. The resulting
|
||||
@@ -43,10 +43,15 @@ Caddy is attached to a controlling tty, the plaintext will
|
||||
not be echoed.
|
||||
|
||||
--algorithm currently only supports 'bcrypt', and is the default.
|
||||
|
||||
--cost defines the bcrypt hashing difficulty.
|
||||
A higher cost increases security by making hashing slower and more CPU-intensive.
|
||||
Default is 14; higher values may significantly impact performance on slower machines.
|
||||
`,
|
||||
CobraFunc: func(cmd *cobra.Command) {
|
||||
cmd.Flags().StringP("plaintext", "p", "", "The plaintext password")
|
||||
cmd.Flags().StringP("algorithm", "a", "bcrypt", "Name of the hash algorithm")
|
||||
cmd.Flags().IntP("cost", "c", 14, "Hashing cost used to create the given hashed password")
|
||||
cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdHashPassword)
|
||||
},
|
||||
})
|
||||
@@ -57,6 +62,7 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) {
|
||||
|
||||
algorithm := fs.String("algorithm")
|
||||
plaintext := []byte(fs.String("plaintext"))
|
||||
cost := fs.Int("cost")
|
||||
|
||||
if len(plaintext) == 0 {
|
||||
fd := int(os.Stdin.Fd())
|
||||
@@ -108,7 +114,7 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) {
|
||||
var hashString string
|
||||
switch algorithm {
|
||||
case "bcrypt":
|
||||
hash, err = BcryptHash{}.Hash(plaintext)
|
||||
hash, err = BcryptHash{}.Hash(plaintext, cost)
|
||||
hashString = string(hash)
|
||||
default:
|
||||
return caddy.ExitCodeFailedStartup, fmt.Errorf("unrecognized hash algorithm: %s", algorithm)
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
package caddyauth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
||||
"github.com/caddyserver/caddy/v2"
|
||||
@@ -38,7 +39,7 @@ func (BcryptHash) CaddyModule() caddy.ModuleInfo {
|
||||
// Compare compares passwords.
|
||||
func (BcryptHash) Compare(hashed, plaintext []byte) (bool, error) {
|
||||
err := bcrypt.CompareHashAndPassword(hashed, plaintext)
|
||||
if err == bcrypt.ErrMismatchedHashAndPassword {
|
||||
if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) {
|
||||
return false, nil
|
||||
}
|
||||
if err != nil {
|
||||
@@ -48,8 +49,8 @@ func (BcryptHash) Compare(hashed, plaintext []byte) (bool, error) {
|
||||
}
|
||||
|
||||
// Hash hashes plaintext using a random salt.
|
||||
func (BcryptHash) Hash(plaintext []byte) ([]byte, error) {
|
||||
return bcrypt.GenerateFromPassword(plaintext, 14)
|
||||
func (BcryptHash) Hash(plaintext []byte, cost int) ([]byte, error) {
|
||||
return bcrypt.GenerateFromPassword(plaintext, cost)
|
||||
}
|
||||
|
||||
// FakeHash returns a fake hash.
|
||||
|
||||
Reference in new issue
Block a user