feat: add bcrypt cost parameter to hash-password

This commit is contained in:
GreyXor committed 2025-07-30 16:54:42 +02:00
1 parent 3bd413546b
commit 19a2de6cea
4 files changed
+17 -9

No files matched your search

+2 -2
View File
@@ -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
}
+3 -2
View File
@@ -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.
+8 -2
View File
@@ -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)
+4 -3
View File
@@ -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.