From e2c20f3ece29d5ef46b0f68e1def843986cd444b Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 09:46:26 +0200 Subject: [PATCH 01/12] feat: add argon2id hash-password command --- modules/caddyhttp/caddyauth/argon2id.go | 107 ++++++++++++++++++ .../caddyauth/{hashes.go => bcrypt.go} | 0 modules/caddyhttp/caddyauth/caddyfile.go | 2 + modules/caddyhttp/caddyauth/command.go | 46 +++++++- 4 files changed, 154 insertions(+), 1 deletion(-) create mode 100644 modules/caddyhttp/caddyauth/argon2id.go rename modules/caddyhttp/caddyauth/{hashes.go => bcrypt.go} (100%) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go new file mode 100644 index 00000000000..5b1d404c8b5 --- /dev/null +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -0,0 +1,107 @@ +// Copyright 2015 Matthew Holt and The Caddy Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package caddyauth + +import ( + "crypto/rand" + "encoding/base64" + "errors" + "fmt" + + "golang.org/x/crypto/argon2" + "golang.org/x/crypto/bcrypt" + + "github.com/caddyserver/caddy/v2" +) + +func init() { + caddy.RegisterModule(Argon2idHash{}) +} + +// Argon2idHash implements the argon2id hash. +type Argon2idHash struct { + salt []byte + time uint32 + memory uint32 + threads uint8 + keyLen uint32 +} + +// CaddyModule returns the Caddy module information. +func (Argon2idHash) CaddyModule() caddy.ModuleInfo { + return caddy.ModuleInfo{ + ID: "http.authentication.hashes.argon2id", + New: func() caddy.Module { return new(Argon2idHash) }, + } +} + +// Compare compares passwords. +func (Argon2idHash) Compare(hashed, plaintext []byte) (bool, error) { + err := bcrypt.CompareHashAndPassword(hashed, plaintext) + if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) { + return false, nil + } + if err != nil { + return false, err + } + return true, nil +} + +// Hash generates an Argon2id hash of the given plaintext using the configured parameters and salt. +func (b Argon2idHash) Hash(plaintext []byte) ([]byte, error) { + key := argon2.IDKey( + plaintext, + b.salt, + b.time, + b.memory, + b.threads, + b.keyLen, + ) + + hash := fmt.Sprintf( + "$argon2id$v=%d$m=%d,t=%d,p=%d$%s$%s", + argon2.Version, + b.memory, + b.time, + b.threads, + base64.RawStdEncoding.EncodeToString(b.salt), + base64.RawStdEncoding.EncodeToString(key), + ) + + return []byte(hash), nil +} + + +// FakeHash returns a fake hash. +func (Argon2idHash) FakeHash() []byte { + // hashed with the following command: + // caddy hash-password --plaintext "antitiming" --algorithm "bcrypt" + return []byte("$2a$14$X3ulqf/iGxnf1k6oMZ.RZeJUoqI9PX2PM4rS5lkIKJXduLGXGPrt6") +} + +// Interface guards +var ( + _ Comparer = (*Argon2idHash)(nil) + _ Hasher = (*Argon2idHash)(nil) +) + +func generateSalt(length int) ([]byte, error) { + salt := make([]byte, length) + _, err := rand.Read(salt) + if err != nil { + return nil, err + } + return salt, nil +} diff --git a/modules/caddyhttp/caddyauth/hashes.go b/modules/caddyhttp/caddyauth/bcrypt.go similarity index 100% rename from modules/caddyhttp/caddyauth/hashes.go rename to modules/caddyhttp/caddyauth/bcrypt.go diff --git a/modules/caddyhttp/caddyauth/caddyfile.go b/modules/caddyhttp/caddyauth/caddyfile.go index cc92477e5ab..5644de3df96 100644 --- a/modules/caddyhttp/caddyauth/caddyfile.go +++ b/modules/caddyhttp/caddyauth/caddyfile.go @@ -64,6 +64,8 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) switch hashName { case "bcrypt": cmp = BcryptHash{} + case "argon2id": + cmp = Argon2idHash{} default: return nil, h.Errf("unrecognized hash algorithm: %s", hashName) } diff --git a/modules/caddyhttp/caddyauth/command.go b/modules/caddyhttp/caddyauth/command.go index 2acaee6c4dd..4eba581bade 100644 --- a/modules/caddyhttp/caddyauth/command.go +++ b/modules/caddyhttp/caddyauth/command.go @@ -42,18 +42,30 @@ hash is written to stdout as a base64 string. Caddy is attached to a controlling tty, the plaintext will not be echoed. ---algorithm currently only supports 'bcrypt', and is the default. +--algorithm 'argon2id' (recommended) or 'bcrypt', the default. --bcrypt-cost sets the bcrypt hashing difficulty. Higher values increase security by making the hash computation slower and more CPU-intensive. If the provided cost is not within the valid range [bcrypt.MinCost, bcrypt.MaxCost], the default value (defaultBcryptCost) will be used instead. Note: Higher cost values can significantly degrade performance on slower systems. + +--argon2id-time + +--argon2id-memory + +--argon2id-threads + +--argon2id-keyLen `, 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().Int("bcrypt-cost", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-time", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-memory", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint8("argon2id-threads", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-keyLen", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdHashPassword) }, }) @@ -117,6 +129,38 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) { switch algorithm { case "bcrypt": hash, err = BcryptHash{cost: bcryptCost}.Hash(plaintext) + hashString = string(hash) + case "argon2id": + salt, err := generateSalt(16) + if err != nil { + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to generate random salt") + } + + time, err := fs.GetUint32("argon2id-time") + if err != nil { + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id time parameter") + } + memory, err := fs.GetUint32("argon2id-memory") + if err != nil { + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id memory parameter") + } + threads, err := fs.GetUint8("argon2id-threads") + if err != nil { + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id threads parameter") + } + keyLen, err := fs.GetUint32("argon2id-keyLen") + if err != nil { + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id keyLen parameter") + } + + hash, err = Argon2idHash{ + salt: salt, + time: time, + memory: memory, + threads: threads, + keyLen: keyLen, + }.Hash(plaintext) + hashString = string(hash) default: return caddy.ExitCodeFailedStartup, fmt.Errorf("unrecognized hash algorithm: %s", algorithm) From 045d4ab5c1b5a93050010dcd4112997fbf44d339 Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 10:07:48 +0200 Subject: [PATCH 02/12] feat: ardon2id owasp safe value --- modules/caddyhttp/caddyauth/argon2id.go | 5 ++--- modules/caddyhttp/caddyauth/command.go | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index 5b1d404c8b5..b4a0ec45241 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -83,12 +83,11 @@ func (b Argon2idHash) Hash(plaintext []byte) ([]byte, error) { return []byte(hash), nil } - // FakeHash returns a fake hash. func (Argon2idHash) FakeHash() []byte { // hashed with the following command: - // caddy hash-password --plaintext "antitiming" --algorithm "bcrypt" - return []byte("$2a$14$X3ulqf/iGxnf1k6oMZ.RZeJUoqI9PX2PM4rS5lkIKJXduLGXGPrt6") + // caddy hash-password --plaintext "antitiming" --algorithm "argon2id" + return []byte("$argon2id$v=19$m=47104,t=1,p=1$1Xs/ODt/ze9BiSqBaSqt4A$yxbSRQXFIBb4GAUQ5aQX3jJLylmfbwAZ2kENe5i4z3Y") } // Interface guards diff --git a/modules/caddyhttp/caddyauth/command.go b/modules/caddyhttp/caddyauth/command.go index 4eba581bade..9a3ee1695fe 100644 --- a/modules/caddyhttp/caddyauth/command.go +++ b/modules/caddyhttp/caddyauth/command.go @@ -62,10 +62,10 @@ Note: Higher cost values can significantly degrade performance on slower systems cmd.Flags().StringP("plaintext", "p", "", "The plaintext password") cmd.Flags().StringP("algorithm", "a", "bcrypt", "Name of the hash algorithm") cmd.Flags().Int("bcrypt-cost", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint32("argon2id-time", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint32("argon2id-memory", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint8("argon2id-threads", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint32("argon2id-keyLen", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-time", 1, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-memory", 46*1024, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint8("argon2id-threads", 1, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-keyLen", 32, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdHashPassword) }, }) From 4fdfeaebe43818665d9fa09c4a8b511f052e939a Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 11:15:41 +0200 Subject: [PATCH 03/12] feat: add argon2id compare method --- modules/caddyhttp/caddyauth/argon2id.go | 98 ++++++++++++++++++++++--- 1 file changed, 88 insertions(+), 10 deletions(-) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index b4a0ec45241..5d7c005a434 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -16,14 +16,14 @@ package caddyauth import ( "crypto/rand" + "crypto/subtle" "encoding/base64" - "errors" "fmt" - - "golang.org/x/crypto/argon2" - "golang.org/x/crypto/bcrypt" + "strconv" + "strings" "github.com/caddyserver/caddy/v2" + "golang.org/x/crypto/argon2" ) func init() { @@ -47,16 +47,30 @@ func (Argon2idHash) CaddyModule() caddy.ModuleInfo { } } -// Compare compares passwords. +// Compare checks if the plaintext password matches the given Argon2id hash. func (Argon2idHash) Compare(hashed, plaintext []byte) (bool, error) { - err := bcrypt.CompareHashAndPassword(hashed, plaintext) - if errors.Is(err, bcrypt.ErrMismatchedHashAndPassword) { - return false, nil + // Decode the stored hash + argHash, storedKey, err := DecodeHash(hashed) + if err != nil { + return false, err } + + // Re-hash the plaintext with the same parameters and salt + computedHash, err := argHash.Hash(plaintext) + if err != nil { + return false, err + } + + _, computedKey, err := DecodeHash(computedHash) if err != nil { return false, err } - return true, nil + + // Use constant-time comparison for security + if subtle.ConstantTimeCompare(storedKey, computedKey) == 1 { + return true, nil + } + return false, nil } // Hash generates an Argon2id hash of the given plaintext using the configured parameters and salt. @@ -83,11 +97,75 @@ func (b Argon2idHash) Hash(plaintext []byte) ([]byte, error) { return []byte(hash), nil } +// DecodeHash parses an Argon2id PHC string into an Argon2idHash struct +// and returns the struct along with the derived key. +// Format: $argon2id$v=19$m=,t=,p=$$ +func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { + parts := strings.Split(string(hash), "$") + if len(parts) != 6 { + return nil, nil, fmt.Errorf("invalid hash format") + } + + if parts[1] != "argon2id" { + return nil, nil, fmt.Errorf("unsupported variant: %s", parts[1]) + } + + // Version + version, err := strconv.Atoi(strings.TrimPrefix(parts[2], "v=")) + if err != nil { + return nil, nil, fmt.Errorf("invalid version: %w", err) + } + if version != argon2.Version { + return nil, nil, fmt.Errorf("incompatible version: %d", version) + } + + // Parameters + params := strings.Split(parts[3], ",") + if len(params) != 3 { + return nil, nil, fmt.Errorf("invalid parameters") + } + + mem, err := strconv.ParseUint(strings.TrimPrefix(params[0], "m="), 10, 32) + if err != nil { + return nil, nil, fmt.Errorf("invalid memory parameter: %w", err) + } + + iter, err := strconv.ParseUint(strings.TrimPrefix(params[1], "t="), 10, 32) + if err != nil { + return nil, nil, fmt.Errorf("invalid iterations parameter: %w", err) + } + + threads, err := strconv.ParseUint(strings.TrimPrefix(params[2], "p="), 10, 8) + if err != nil { + return nil, nil, fmt.Errorf("invalid parallelism parameter: %w", err) + } + + // Salt + salt, err := base64.RawStdEncoding.Strict().DecodeString(parts[4]) + if err != nil { + return nil, nil, fmt.Errorf("decode salt: %w", err) + } + + // Key + key, err := base64.RawStdEncoding.Strict().DecodeString(parts[5]) + if err != nil { + return nil, nil, fmt.Errorf("decode key: %w", err) + } + + return &Argon2idHash{ + salt: salt, + time: uint32(iter), + memory: uint32(mem), + threads: uint8(threads), + keyLen: uint32(len(key)), + }, key, nil +} + // FakeHash returns a fake hash. func (Argon2idHash) FakeHash() []byte { // hashed with the following command: // caddy hash-password --plaintext "antitiming" --algorithm "argon2id" - return []byte("$argon2id$v=19$m=47104,t=1,p=1$1Xs/ODt/ze9BiSqBaSqt4A$yxbSRQXFIBb4GAUQ5aQX3jJLylmfbwAZ2kENe5i4z3Y") + return []byte("$argon2id$v=19$m=47104,t=1,p=1$OAdQWX6By8ZZqB0vuW8pmQ$go5ZgOWvTOS5zhJmOrXEhV4LAnxBXUFwc/KVJfy2X4k") } // Interface guards From e68483e40836f73cc37cac504dff2f2663e4e741 Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 11:16:34 +0200 Subject: [PATCH 04/12] chore: fmt argon2id --- modules/caddyhttp/caddyauth/argon2id.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index 5d7c005a434..11a7a8843ea 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -22,8 +22,9 @@ import ( "strconv" "strings" - "github.com/caddyserver/caddy/v2" "golang.org/x/crypto/argon2" + + "github.com/caddyserver/caddy/v2" ) func init() { From 51dce0cc25261aef15d06e902a2dbe5e0ee143a1 Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 11:32:49 +0200 Subject: [PATCH 05/12] docs: more argon2id docs --- modules/caddyhttp/caddyauth/argon2id.go | 4 +- modules/caddyhttp/caddyauth/bcrypt.go | 5 +- modules/caddyhttp/caddyauth/caddyfile.go | 4 +- modules/caddyhttp/caddyauth/command.go | 60 +++++++++++++++++------- 4 files changed, 51 insertions(+), 22 deletions(-) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index 11a7a8843ea..babf1c8d7c5 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -31,6 +31,8 @@ func init() { caddy.RegisterModule(Argon2idHash{}) } +const argon2idName = "argon2id" + // Argon2idHash implements the argon2id hash. type Argon2idHash struct { salt []byte @@ -107,7 +109,7 @@ func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { return nil, nil, fmt.Errorf("invalid hash format") } - if parts[1] != "argon2id" { + if parts[1] != argon2idName { return nil, nil, fmt.Errorf("unsupported variant: %s", parts[1]) } diff --git a/modules/caddyhttp/caddyauth/bcrypt.go b/modules/caddyhttp/caddyauth/bcrypt.go index ea91f24e253..f6940996eaa 100644 --- a/modules/caddyhttp/caddyauth/bcrypt.go +++ b/modules/caddyhttp/caddyauth/bcrypt.go @@ -27,7 +27,10 @@ func init() { } // defaultBcryptCost cost 14 strikes a solid balance between security, usability, and hardware performance -const defaultBcryptCost = 14 +const ( + bcryptName = "bcrypt" + defaultBcryptCost = 14 +) // BcryptHash implements the bcrypt hash. type BcryptHash struct { diff --git a/modules/caddyhttp/caddyauth/caddyfile.go b/modules/caddyhttp/caddyauth/caddyfile.go index 5644de3df96..8f2b8ee592a 100644 --- a/modules/caddyhttp/caddyauth/caddyfile.go +++ b/modules/caddyhttp/caddyauth/caddyfile.go @@ -51,7 +51,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) var hashName string switch len(args) { case 0: - hashName = "bcrypt" + hashName = bcryptName case 1: hashName = args[0] case 2: @@ -62,7 +62,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) } switch hashName { - case "bcrypt": + case bcryptName: cmp = BcryptHash{} case "argon2id": cmp = Argon2idHash{} diff --git a/modules/caddyhttp/caddyauth/command.go b/modules/caddyhttp/caddyauth/command.go index 9a3ee1695fe..52832b50726 100644 --- a/modules/caddyhttp/caddyauth/command.go +++ b/modules/caddyhttp/caddyauth/command.go @@ -29,6 +29,13 @@ import ( "github.com/caddyserver/caddy/v2" ) +const ( + defaultArgon2idTime = 1 + defaultArgon2idMemory = 46 * 1024 + defaultArgon2idThreads = 1 + defaultArgon2idKeylen = 32 +) + func init() { caddycmd.RegisterCommand(caddycmd.Command{ Name: "hash-password", @@ -38,34 +45,51 @@ func init() { Convenient way to hash a plaintext password. The resulting hash is written to stdout as a base64 string. ---plaintext, when omitted, will be read from stdin. If -Caddy is attached to a controlling tty, the plaintext will -not be echoed. +--plaintext + The password to hash. If omitted, it will be read from stdin. + If Caddy is attached to a controlling TTY, the input will not be echoed. + +--algorithm + Selects the hashing algorithm. Valid options are: + * 'argon2id' (recommended for modern security) + * 'bcrypt' (widely supported, slower, configurable cost) + Defaults to 'argon2id' for maximum security. Argon2id is resistant to + GPU attacks and memory-hard, making it ideal for password storage. + +bcrypt-specific parameters: ---algorithm 'argon2id' (recommended) or 'bcrypt', the default. +--bcrypt-cost + Sets the bcrypt hashing difficulty. Higher values increase security by + making the hash computation slower and more CPU-intensive. + Must be within the valid range [bcrypt.MinCost, bcrypt.MaxCost]. + If omitted or invalid, the default cost is used. ---bcrypt-cost sets the bcrypt hashing difficulty. -Higher values increase security by making the hash computation slower and more CPU-intensive. -If the provided cost is not within the valid range [bcrypt.MinCost, bcrypt.MaxCost], -the default value (defaultBcryptCost) will be used instead. -Note: Higher cost values can significantly degrade performance on slower systems. +Argon2id-specific parameters: --argon2id-time + Number of iterations to perform. Increasing this makes + hashing slower and more resistant to brute-force attacks. --argon2id-memory + Amount of memory (in KiB) to use during hashing. + Larger values increase resistance to GPU/ASIC attacks. --argon2id-threads + Number of CPU threads to use. Increase for faster hashing + on multi-core systems. ---argon2id-keyLen +--argon2id-keylen + Length of the resulting hash in bytes. Longer keys increase + security but slightly increase storage size. `, 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().StringP("algorithm", "a", bcryptName, "Name of the hash algorithm") cmd.Flags().Int("bcrypt-cost", defaultBcryptCost, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint32("argon2id-time", 1, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint32("argon2id-memory", 46*1024, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint8("argon2id-threads", 1, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") - cmd.Flags().Uint32("argon2id-keyLen", 32, "Bcrypt hashing cost (only used with 'bcrypt' algorithm)") + cmd.Flags().Uint32("argon2id-time", defaultArgon2idTime, "Number of iterations for Argon2id hashing. Increasing this makes the hash slower and more resistant to brute-force attacks.") + cmd.Flags().Uint32("argon2id-memory", defaultArgon2idMemory, "Memory to use in KiB for Argon2id hashing. Larger values increase resistance to GPU/ASIC attacks.") + cmd.Flags().Uint8("argon2id-threads", defaultArgon2idThreads, "Number of CPU threads to use for Argon2id hashing. Increase for faster hashing on multi-core systems.") + cmd.Flags().Uint32("argon2id-keylen", defaultArgon2idKeylen, "Length of the resulting Argon2id hash in bytes. Longer hashes increase security but slightly increase storage size.") cmd.RunE = caddycmd.WrapCommandFuncForCobra(cmdHashPassword) }, }) @@ -127,10 +151,10 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) { var hash []byte var hashString string switch algorithm { - case "bcrypt": + case bcryptName: hash, err = BcryptHash{cost: bcryptCost}.Hash(plaintext) hashString = string(hash) - case "argon2id": + case argon2idName: salt, err := generateSalt(16) if err != nil { return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to generate random salt") @@ -148,7 +172,7 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) { if err != nil { return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id threads parameter") } - keyLen, err := fs.GetUint32("argon2id-keyLen") + keyLen, err := fs.GetUint32("argon2id-keylen") if err != nil { return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id keyLen parameter") } From 84b3fca49808b088f4745abb617ff41288745e4a Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 11:44:04 +0200 Subject: [PATCH 06/12] chore: upgrade x/crypto dep --- .golangci.yml | 118 -------------------------------------------------- go.mod | 12 ++--- go.sum | 24 +++++----- 3 files changed, 18 insertions(+), 136 deletions(-) delete mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml deleted file mode 100644 index 0f1082e729b..00000000000 --- a/.golangci.yml +++ /dev/null @@ -1,118 +0,0 @@ -version: "2" -run: - issues-exit-code: 1 - tests: false -output: - formats: - text: - path: stdout - print-linter-name: true - print-issued-lines: true -linters: - default: none - enable: - - asasalint - - asciicheck - - bidichk - - bodyclose - - decorder - - dogsled - - dupl - - dupword - - durationcheck - - errcheck - - errname - - exhaustive - - gosec - - govet - - importas - - ineffassign - - misspell - - prealloc - - promlinter - - sloglint - - sqlclosecheck - - staticcheck - - testableexamples - - testifylint - - tparallel - - unconvert - - unused - - wastedassign - - whitespace - - zerologlint - settings: - staticcheck: - checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1006", "-QF1008"] # default, and exclude 1 more undesired check - errcheck: - exclude-functions: - - fmt.* - - (go.uber.org/zap/zapcore.ObjectEncoder).AddObject - - (go.uber.org/zap/zapcore.ObjectEncoder).AddArray - exhaustive: - ignore-enum-types: reflect.Kind|svc.Cmd - exclusions: - generated: lax - presets: - - comments - - common-false-positives - - legacy - - std-error-handling - rules: - - linters: - - gosec - text: G115 # TODO: Either we should fix the issues or nuke the linter if it's bad - - linters: - - gosec - text: G107 # we aren't calling unknown URL - - linters: - - gosec - text: G203 # as a web server that's expected to handle any template, this is totally in the hands of the user. - - linters: - - gosec - text: G204 # we're shelling out to known commands, not relying on user-defined input. - - linters: - - gosec - # the choice of weakrand is deliberate, hence the named import "weakrand" - path: modules/caddyhttp/reverseproxy/selectionpolicies.go - text: G404 - - linters: - - gosec - path: modules/caddyhttp/reverseproxy/streaming.go - text: G404 - - linters: - - dupl - path: modules/logging/filters.go - - linters: - - dupl - path: modules/caddyhttp/matchers.go - - linters: - - dupl - path: modules/caddyhttp/vars.go - - linters: - - errcheck - path: _test\.go - paths: - - third_party$ - - builtin$ - - examples$ -formatters: - enable: - - gci - - gofmt - - gofumpt - - goimports - settings: - gci: - sections: - - standard # Standard section: captures all standard packages. - - default # Default section: contains all imports that could not be matched to another section type. - - prefix(github.com/caddyserver/caddy/v2/cmd) # ensure that this is always at the top and always has a line break. - - prefix(github.com/caddyserver/caddy) # Custom section: groups all imports with the specified Prefix. - custom-order: true - exclusions: - generated: lax - paths: - - third_party$ - - builtin$ - - examples$ diff --git a/go.mod b/go.mod index 4c66c62f1f9..dbb66f90e27 100644 --- a/go.mod +++ b/go.mod @@ -37,11 +37,11 @@ require ( go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.0 go.uber.org/zap/exp v0.3.0 - golang.org/x/crypto v0.40.0 + golang.org/x/crypto v0.41.0 golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810 golang.org/x/net v0.42.0 golang.org/x/sync v0.16.0 - golang.org/x/term v0.33.0 + golang.org/x/term v0.34.0 golang.org/x/time v0.12.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 @@ -153,10 +153,10 @@ require ( go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.step.sm/crypto v0.67.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.25.0 // indirect - golang.org/x/sys v0.34.0 - golang.org/x/text v0.27.0 // indirect - golang.org/x/tools v0.34.0 // indirect + golang.org/x/mod v0.26.0 // indirect + golang.org/x/sys v0.35.0 + golang.org/x/text v0.28.0 // indirect + golang.org/x/tools v0.35.0 // indirect google.golang.org/grpc v1.73.0 // indirect google.golang.org/protobuf v1.36.6 // indirect howett.net/plist v1.0.0 // indirect diff --git a/go.sum b/go.sum index c97047aec23..7b056c75559 100644 --- a/go.sum +++ b/go.sum @@ -502,8 +502,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM= -golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY= +golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= +golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810 h1:V5+zy0jmgNYmK1uW/sPpBw8ioFvalrhaUrYWmu1Fpe4= golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810/go.mod h1:lxN5T34bK4Z/i6cMaU7frUU57VkDXFD4Kamfl/cp9oU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -517,8 +517,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= -golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= +golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -582,8 +582,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= +golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -594,8 +594,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg= -golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0= +golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= +golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -607,8 +607,8 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= +golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= @@ -623,8 +623,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= -golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= +golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= From ab08be79319d25548ca40f90de3c29434e200be4 Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 11:44:57 +0200 Subject: [PATCH 07/12] revert: remove golangci --- .golangci.yml | 118 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 .golangci.yml diff --git a/.golangci.yml b/.golangci.yml new file mode 100644 index 00000000000..0f1082e729b --- /dev/null +++ b/.golangci.yml @@ -0,0 +1,118 @@ +version: "2" +run: + issues-exit-code: 1 + tests: false +output: + formats: + text: + path: stdout + print-linter-name: true + print-issued-lines: true +linters: + default: none + enable: + - asasalint + - asciicheck + - bidichk + - bodyclose + - decorder + - dogsled + - dupl + - dupword + - durationcheck + - errcheck + - errname + - exhaustive + - gosec + - govet + - importas + - ineffassign + - misspell + - prealloc + - promlinter + - sloglint + - sqlclosecheck + - staticcheck + - testableexamples + - testifylint + - tparallel + - unconvert + - unused + - wastedassign + - whitespace + - zerologlint + settings: + staticcheck: + checks: ["all", "-ST1000", "-ST1003", "-ST1016", "-ST1020", "-ST1021", "-ST1022", "-QF1006", "-QF1008"] # default, and exclude 1 more undesired check + errcheck: + exclude-functions: + - fmt.* + - (go.uber.org/zap/zapcore.ObjectEncoder).AddObject + - (go.uber.org/zap/zapcore.ObjectEncoder).AddArray + exhaustive: + ignore-enum-types: reflect.Kind|svc.Cmd + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - gosec + text: G115 # TODO: Either we should fix the issues or nuke the linter if it's bad + - linters: + - gosec + text: G107 # we aren't calling unknown URL + - linters: + - gosec + text: G203 # as a web server that's expected to handle any template, this is totally in the hands of the user. + - linters: + - gosec + text: G204 # we're shelling out to known commands, not relying on user-defined input. + - linters: + - gosec + # the choice of weakrand is deliberate, hence the named import "weakrand" + path: modules/caddyhttp/reverseproxy/selectionpolicies.go + text: G404 + - linters: + - gosec + path: modules/caddyhttp/reverseproxy/streaming.go + text: G404 + - linters: + - dupl + path: modules/logging/filters.go + - linters: + - dupl + path: modules/caddyhttp/matchers.go + - linters: + - dupl + path: modules/caddyhttp/vars.go + - linters: + - errcheck + path: _test\.go + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: + gci: + sections: + - standard # Standard section: captures all standard packages. + - default # Default section: contains all imports that could not be matched to another section type. + - prefix(github.com/caddyserver/caddy/v2/cmd) # ensure that this is always at the top and always has a line break. + - prefix(github.com/caddyserver/caddy) # Custom section: groups all imports with the specified Prefix. + custom-order: true + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ From 8f6b01e1951e73a36c2c1d74729a75972999947d Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 12:08:07 +0200 Subject: [PATCH 08/12] refactor: argon2id decode --- modules/caddyhttp/caddyauth/argon2id.go | 57 +++++++++++++----------- modules/caddyhttp/caddyauth/caddyfile.go | 2 +- modules/caddyhttp/caddyauth/command.go | 31 ++++--------- 3 files changed, 39 insertions(+), 51 deletions(-) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index babf1c8d7c5..c9b650f8ec2 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -31,9 +31,16 @@ func init() { caddy.RegisterModule(Argon2idHash{}) } -const argon2idName = "argon2id" +const ( + argon2idName = "argon2id" + defaultArgon2idTime = 1 + defaultArgon2idMemory = 46 * 1024 + defaultArgon2idThreads = 1 + defaultArgon2idKeylen = 32 + defaultSaltLength = 16 +) -// Argon2idHash implements the argon2id hash. +// Argon2idHash implements the Argon2id password hashing. type Argon2idHash struct { salt []byte time uint32 @@ -52,24 +59,21 @@ func (Argon2idHash) CaddyModule() caddy.ModuleInfo { // Compare checks if the plaintext password matches the given Argon2id hash. func (Argon2idHash) Compare(hashed, plaintext []byte) (bool, error) { - // Decode the stored hash argHash, storedKey, err := DecodeHash(hashed) if err != nil { return false, err } - // Re-hash the plaintext with the same parameters and salt - computedHash, err := argHash.Hash(plaintext) - if err != nil { - return false, err - } - - _, computedKey, err := DecodeHash(computedHash) - if err != nil { - return false, err - } + computedKey := argon2.IDKey( + plaintext, + argHash.salt, + argHash.time, + argHash.memory, + argHash.threads, + argHash.keyLen, + ) - // Use constant-time comparison for security + // Constant-time comparison for security if subtle.ConstantTimeCompare(storedKey, computedKey) == 1 { return true, nil } @@ -78,6 +82,14 @@ func (Argon2idHash) Compare(hashed, plaintext []byte) (bool, error) { // Hash generates an Argon2id hash of the given plaintext using the configured parameters and salt. func (b Argon2idHash) Hash(plaintext []byte) ([]byte, error) { + if b.salt == nil { + s, err := generateSalt(defaultSaltLength) + if err != nil { + return nil, err + } + b.salt = s + } + key := argon2.IDKey( plaintext, b.salt, @@ -100,9 +112,7 @@ func (b Argon2idHash) Hash(plaintext []byte) ([]byte, error) { return []byte(hash), nil } -// DecodeHash parses an Argon2id PHC string into an Argon2idHash struct -// and returns the struct along with the derived key. -// Format: $argon2id$v=19$m=,t=,p=$$ +// DecodeHash parses an Argon2id PHC string into an Argon2idHash struct and returns the struct along with the derived key. func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { parts := strings.Split(string(hash), "$") if len(parts) != 6 { @@ -113,7 +123,6 @@ func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { return nil, nil, fmt.Errorf("unsupported variant: %s", parts[1]) } - // Version version, err := strconv.Atoi(strings.TrimPrefix(parts[2], "v=")) if err != nil { return nil, nil, fmt.Errorf("invalid version: %w", err) @@ -122,7 +131,6 @@ func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { return nil, nil, fmt.Errorf("incompatible version: %d", version) } - // Parameters params := strings.Split(parts[3], ",") if len(params) != 3 { return nil, nil, fmt.Errorf("invalid parameters") @@ -143,13 +151,11 @@ func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { return nil, nil, fmt.Errorf("invalid parallelism parameter: %w", err) } - // Salt salt, err := base64.RawStdEncoding.Strict().DecodeString(parts[4]) if err != nil { return nil, nil, fmt.Errorf("decode salt: %w", err) } - // Key key, err := base64.RawStdEncoding.Strict().DecodeString(parts[5]) if err != nil { return nil, nil, fmt.Errorf("decode key: %w", err) @@ -164,10 +170,8 @@ func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { }, key, nil } -// FakeHash returns a fake hash. +// FakeHash returns a constant fake hash for timing attacks mitigation. func (Argon2idHash) FakeHash() []byte { - // hashed with the following command: - // caddy hash-password --plaintext "antitiming" --algorithm "argon2id" return []byte("$argon2id$v=19$m=47104,t=1,p=1$OAdQWX6By8ZZqB0vuW8pmQ$go5ZgOWvTOS5zhJmOrXEhV4LAnxBXUFwc/KVJfy2X4k") } @@ -179,9 +183,8 @@ var ( func generateSalt(length int) ([]byte, error) { salt := make([]byte, length) - _, err := rand.Read(salt) - if err != nil { - return nil, err + if _, err := rand.Read(salt); err != nil { + return nil, fmt.Errorf("failed to generate salt: %w", err) } return salt, nil } diff --git a/modules/caddyhttp/caddyauth/caddyfile.go b/modules/caddyhttp/caddyauth/caddyfile.go index 8f2b8ee592a..99a33aff596 100644 --- a/modules/caddyhttp/caddyauth/caddyfile.go +++ b/modules/caddyhttp/caddyauth/caddyfile.go @@ -64,7 +64,7 @@ func parseCaddyfile(h httpcaddyfile.Helper) (caddyhttp.MiddlewareHandler, error) switch hashName { case bcryptName: cmp = BcryptHash{} - case "argon2id": + case argon2idName: cmp = Argon2idHash{} default: return nil, h.Errf("unrecognized hash algorithm: %s", hashName) diff --git a/modules/caddyhttp/caddyauth/command.go b/modules/caddyhttp/caddyauth/command.go index 52832b50726..e9c513005f2 100644 --- a/modules/caddyhttp/caddyauth/command.go +++ b/modules/caddyhttp/caddyauth/command.go @@ -29,17 +29,10 @@ import ( "github.com/caddyserver/caddy/v2" ) -const ( - defaultArgon2idTime = 1 - defaultArgon2idMemory = 46 * 1024 - defaultArgon2idThreads = 1 - defaultArgon2idKeylen = 32 -) - func init() { caddycmd.RegisterCommand(caddycmd.Command{ Name: "hash-password", - Usage: "[--plaintext ] [--algorithm ] [--bcrypt-cost ]", + Usage: "[--plaintext ] [--algorithm ] [--bcrypt-cost ] [--argon2id-time ] [--argon2id-memory ] [--argon2id-threads ] [--argon2id-keylen ]", Short: "Hashes a password and writes base64", Long: ` Convenient way to hash a plaintext password. The resulting @@ -52,9 +45,7 @@ hash is written to stdout as a base64 string. --algorithm Selects the hashing algorithm. Valid options are: * 'argon2id' (recommended for modern security) - * 'bcrypt' (widely supported, slower, configurable cost) - Defaults to 'argon2id' for maximum security. Argon2id is resistant to - GPU attacks and memory-hard, making it ideal for password storage. + * 'bcrypt' (legacy, slower, configurable cost) bcrypt-specific parameters: @@ -71,7 +62,7 @@ Argon2id-specific parameters: hashing slower and more resistant to brute-force attacks. --argon2id-memory - Amount of memory (in KiB) to use during hashing. + Amount of memory to use during hashing. Larger values increase resistance to GPU/ASIC attacks. --argon2id-threads @@ -155,30 +146,24 @@ func cmdHashPassword(fs caddycmd.Flags) (int, error) { hash, err = BcryptHash{cost: bcryptCost}.Hash(plaintext) hashString = string(hash) case argon2idName: - salt, err := generateSalt(16) - if err != nil { - return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to generate random salt") - } - time, err := fs.GetUint32("argon2id-time") if err != nil { - return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id time parameter") + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id time parameter: %w", err) } memory, err := fs.GetUint32("argon2id-memory") if err != nil { - return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id memory parameter") + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id memory parameter: %w", err) } threads, err := fs.GetUint8("argon2id-threads") if err != nil { - return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id threads parameter") + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id threads parameter: %w", err) } keyLen, err := fs.GetUint32("argon2id-keylen") if err != nil { - return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id keyLen parameter") + return caddy.ExitCodeFailedStartup, fmt.Errorf("failed to get argon2id keylen parameter: %w", err) } - hash, err = Argon2idHash{ - salt: salt, + hash, _ = Argon2idHash{ time: time, memory: memory, threads: threads, From 6be0e5e07e9a2d612b8174ec5336fb11483eef34 Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 17 Aug 2025 12:47:29 +0200 Subject: [PATCH 09/12] chore: update deps --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- modules/caddyhttp/caddyauth/argon2id.go | 4 +++- 3 files changed, 18 insertions(+), 16 deletions(-) diff --git a/go.mod b/go.mod index dbb66f90e27..62b1b423662 100644 --- a/go.mod +++ b/go.mod @@ -38,8 +38,8 @@ require ( go.uber.org/zap v1.27.0 go.uber.org/zap/exp v0.3.0 golang.org/x/crypto v0.41.0 - golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810 - golang.org/x/net v0.42.0 + golang.org/x/crypto/x509roots/fallback v0.0.0-20250813150022-44ecf3af9978 + golang.org/x/net v0.43.0 golang.org/x/sync v0.16.0 golang.org/x/term v0.34.0 golang.org/x/time v0.12.0 @@ -90,7 +90,7 @@ require ( go.opentelemetry.io/contrib/propagators/jaeger v1.37.0 // indirect go.opentelemetry.io/contrib/propagators/ot v1.37.0 // indirect go.uber.org/mock v0.5.2 // indirect - golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 // indirect + golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 // indirect golang.org/x/oauth2 v0.30.0 // indirect google.golang.org/api v0.240.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250603155806-513f23925822 // indirect @@ -153,10 +153,10 @@ require ( go.opentelemetry.io/proto/otlp v1.7.0 // indirect go.step.sm/crypto v0.67.0 go.uber.org/multierr v1.11.0 // indirect - golang.org/x/mod v0.26.0 // indirect + golang.org/x/mod v0.27.0 // indirect golang.org/x/sys v0.35.0 golang.org/x/text v0.28.0 // indirect - golang.org/x/tools v0.35.0 // indirect + golang.org/x/tools v0.36.0 // indirect google.golang.org/grpc v1.73.0 // indirect google.golang.org/protobuf v1.36.6 // indirect howett.net/plist v1.0.0 // indirect diff --git a/go.sum b/go.sum index 7b056c75559..bc4693aa3b6 100644 --- a/go.sum +++ b/go.sum @@ -504,11 +504,11 @@ golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt7 golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810 h1:V5+zy0jmgNYmK1uW/sPpBw8ioFvalrhaUrYWmu1Fpe4= -golang.org/x/crypto/x509roots/fallback v0.0.0-20250305170421-49bf5b80c810/go.mod h1:lxN5T34bK4Z/i6cMaU7frUU57VkDXFD4Kamfl/cp9oU= +golang.org/x/crypto/x509roots/fallback v0.0.0-20250813150022-44ecf3af9978 h1:oZsBVkmy+/fe11mKcUgNRiyYjI3pl8Ua3ObG7Mx693E= +golang.org/x/crypto/x509roots/fallback v0.0.0-20250813150022-44ecf3af9978/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0 h1:R84qjqJb5nVJMxqWYb3np9L5ZsaDtB+a39EqjV0JSUM= -golang.org/x/exp v0.0.0-20250408133849-7e4ce0ab07d0/go.mod h1:S9Xr4PYopiDyqSyp5NjCrhFrqg6A5zA2E/iPHPhqnS8= +golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE= +golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -517,8 +517,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= -golang.org/x/mod v0.26.0 h1:EGMPT//Ezu+ylkCijjPc+f4Aih7sZvaAr+O3EHBxvZg= -golang.org/x/mod v0.26.0/go.mod h1:/j6NAhSk8iQ723BGAUyoAcn7SlD7s15Dp9Nd/SfeaFQ= +golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= +golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -535,8 +535,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= +golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= +golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -623,8 +623,8 @@ golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk= -golang.org/x/tools v0.35.0 h1:mBffYraMEf7aa0sB+NuKnuCy8qI/9Bughn8dC2Gu5r0= -golang.org/x/tools v0.35.0/go.mod h1:NKdj5HkL/73byiZSJjqJgKn3ep7KjFkBOkR/Hps3VPw= +golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= +golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index c9b650f8ec2..401d3e1a259 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -172,7 +172,9 @@ func DecodeHash(hash []byte) (*Argon2idHash, []byte, error) { // FakeHash returns a constant fake hash for timing attacks mitigation. func (Argon2idHash) FakeHash() []byte { - return []byte("$argon2id$v=19$m=47104,t=1,p=1$OAdQWX6By8ZZqB0vuW8pmQ$go5ZgOWvTOS5zhJmOrXEhV4LAnxBXUFwc/KVJfy2X4k") + // hashed with the following command: + // caddy hash-password --plaintext "antitiming" --algorithm "argon2id" + return []byte("$argon2id$v=19$m=47104,t=1,p=1$P2nzckEdTZ3bxCiBCkRTyA$xQL3Z32eo5jKl7u5tcIsnEKObYiyNZQQf5/4sAau6Pg") } // Interface guards From 8c58c5197971e919e5513bb62bfc54a19c5413e1 Mon Sep 17 00:00:00 2001 From: GreyXor Date: Wed, 20 Aug 2025 21:31:21 +0200 Subject: [PATCH 10/12] refactor: simplify argon2id compare return --- modules/caddyhttp/caddyauth/argon2id.go | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/modules/caddyhttp/caddyauth/argon2id.go b/modules/caddyhttp/caddyauth/argon2id.go index 401d3e1a259..f1070ce4887 100644 --- a/modules/caddyhttp/caddyauth/argon2id.go +++ b/modules/caddyhttp/caddyauth/argon2id.go @@ -73,11 +73,7 @@ func (Argon2idHash) Compare(hashed, plaintext []byte) (bool, error) { argHash.keyLen, ) - // Constant-time comparison for security - if subtle.ConstantTimeCompare(storedKey, computedKey) == 1 { - return true, nil - } - return false, nil + return subtle.ConstantTimeCompare(storedKey, computedKey) == 1, nil } // Hash generates an Argon2id hash of the given plaintext using the configured parameters and salt. From 281685d3d88ac43af024353d721ba1ecc73b8fda Mon Sep 17 00:00:00 2001 From: GreyXor Date: Fri, 19 Sep 2025 12:59:56 +0200 Subject: [PATCH 11/12] chore: upgrade dependencies --- go.mod | 16 ++++++++-------- go.sum | 32 ++++++++++++++++---------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/go.mod b/go.mod index 62b1b423662..f85b57d01f3 100644 --- a/go.mod +++ b/go.mod @@ -37,12 +37,12 @@ require ( go.uber.org/automaxprocs v1.6.0 go.uber.org/zap v1.27.0 go.uber.org/zap/exp v0.3.0 - golang.org/x/crypto v0.41.0 - golang.org/x/crypto/x509roots/fallback v0.0.0-20250813150022-44ecf3af9978 - golang.org/x/net v0.43.0 - golang.org/x/sync v0.16.0 - golang.org/x/term v0.34.0 - golang.org/x/time v0.12.0 + golang.org/x/crypto v0.42.0 + golang.org/x/crypto/x509roots/fallback v0.0.0-20250916063316-ddb4e80c6ad3 + golang.org/x/net v0.44.0 + golang.org/x/sync v0.17.0 + golang.org/x/term v0.35.0 + golang.org/x/time v0.13.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 ) @@ -154,8 +154,8 @@ require ( go.step.sm/crypto v0.67.0 go.uber.org/multierr v1.11.0 // indirect golang.org/x/mod v0.27.0 // indirect - golang.org/x/sys v0.35.0 - golang.org/x/text v0.28.0 // indirect + golang.org/x/sys v0.36.0 + golang.org/x/text v0.29.0 // indirect golang.org/x/tools v0.36.0 // indirect google.golang.org/grpc v1.73.0 // indirect google.golang.org/protobuf v1.36.6 // indirect diff --git a/go.sum b/go.sum index bc4693aa3b6..e98f297033a 100644 --- a/go.sum +++ b/go.sum @@ -502,10 +502,10 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt70= golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= -golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= -golang.org/x/crypto/x509roots/fallback v0.0.0-20250813150022-44ecf3af9978 h1:oZsBVkmy+/fe11mKcUgNRiyYjI3pl8Ua3ObG7Mx693E= -golang.org/x/crypto/x509roots/fallback v0.0.0-20250813150022-44ecf3af9978/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18= +golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= +golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= +golang.org/x/crypto/x509roots/fallback v0.0.0-20250916063316-ddb4e80c6ad3 h1:tDKyJPWK+Jz1G5l0ECsDbiDrLveZP7k6+i2dUdxz9os= +golang.org/x/crypto/x509roots/fallback v0.0.0-20250916063316-ddb4e80c6ad3/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= @@ -535,8 +535,8 @@ golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= -golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= -golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= +golang.org/x/net v0.44.0 h1:evd8IRDyfNBMBTTY5XRF1vaZlD+EmWx6x8PkhR04H/I= +golang.org/x/net v0.44.0/go.mod h1:ECOoLqd5U3Lhyeyo/QDCEVQ4sNgYsqvCZ722XogGieY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -556,8 +556,8 @@ golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= -golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.17.0 h1:l60nONMj9l5drqw6jlhIELNv9I0A4OFgRsG9k2oT9Ug= +golang.org/x/sync v0.17.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -582,8 +582,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= -golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.36.0 h1:KVRy2GtZBrk1cBYA7MKu5bEZFxQk4NIDV6RLVcC8o0k= +golang.org/x/sys v0.36.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -594,8 +594,8 @@ golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= golang.org/x/term v0.24.0/go.mod h1:lOBK/LVxemqiMij05LGJ0tzNr8xlmwBRJ81PX6wVLH8= golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= -golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= +golang.org/x/term v0.35.0 h1:bZBVKBudEyhRcajGcNc3jIfWPqV4y/Kt2XcoigOWtDQ= +golang.org/x/term v0.35.0/go.mod h1:TPGtkTLesOwf2DE8CgVYiZinHAOuy5AYUYT1lENIZnA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -607,12 +607,12 @@ golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= -golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= +golang.org/x/text v0.29.0 h1:1neNs90w9YzJ9BocxfsQNHKuAT4pkghyXc4nhZ6sJvk= +golang.org/x/text v0.29.0/go.mod h1:7MhJOA9CD2qZyOKYazxdYMF85OwPdEr9jTtBpO7ydH4= golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.12.0 h1:ScB/8o8olJvc+CQPWrK3fPZNfh7qgwCrY0zJmoEQLSE= -golang.org/x/time v0.12.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg= +golang.org/x/time v0.13.0 h1:eUlYslOIt32DgYD6utsuUeHs4d7AsEYLuIAdg7FlYgI= +golang.org/x/time v0.13.0/go.mod h1:eL/Oa2bBBK0TkX57Fyni+NgnyQQN4LitPmob2Hjnqw4= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 3471849d960da316937911f18356c6270fbc959d Mon Sep 17 00:00:00 2001 From: GreyXor Date: Sun, 5 Oct 2025 12:58:59 +0200 Subject: [PATCH 12/12] chore: upgrade dependencies --- go.mod | 8 ++++---- go.sum | 16 ++++++++-------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/go.mod b/go.mod index a3ddeae3cd4..48ecf24960c 100644 --- a/go.mod +++ b/go.mod @@ -38,7 +38,7 @@ require ( go.uber.org/zap v1.27.0 go.uber.org/zap/exp v0.3.0 golang.org/x/crypto v0.42.0 - golang.org/x/crypto/x509roots/fallback v0.0.0-20250916063316-ddb4e80c6ad3 + golang.org/x/crypto/x509roots/fallback v0.0.0-20250927194341-2beaa59a3c99 golang.org/x/net v0.44.0 golang.org/x/sync v0.17.0 golang.org/x/term v0.35.0 @@ -94,7 +94,7 @@ require ( golang.org/x/oauth2 v0.30.0 // indirect google.golang.org/api v0.247.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 // indirect google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 // indirect ) @@ -157,7 +157,7 @@ require ( golang.org/x/sys v0.36.0 golang.org/x/text v0.29.0 // indirect golang.org/x/tools v0.36.0 // indirect - google.golang.org/grpc v1.73.0 // indirect - google.golang.org/protobuf v1.36.6 // indirect + google.golang.org/grpc v1.75.1 // indirect + google.golang.org/protobuf v1.36.10 // indirect howett.net/plist v1.0.0 // indirect ) diff --git a/go.sum b/go.sum index 2813bda4cf4..5e7ecf73d48 100644 --- a/go.sum +++ b/go.sum @@ -504,8 +504,8 @@ golang.org/x/crypto v0.27.0/go.mod h1:1Xngt8kV6Dvbssa53Ziq6Eqn0HqbZi5Z6R0ZpwQzt7 golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= golang.org/x/crypto v0.42.0 h1:chiH31gIWm57EkTXpwnqf8qeuMUi0yekh6mT2AvFlqI= golang.org/x/crypto v0.42.0/go.mod h1:4+rDnOTJhQCx2q7/j6rAN5XDw8kPjeaXEUR2eL94ix8= -golang.org/x/crypto/x509roots/fallback v0.0.0-20250916063316-ddb4e80c6ad3 h1:tDKyJPWK+Jz1G5l0ECsDbiDrLveZP7k6+i2dUdxz9os= -golang.org/x/crypto/x509roots/fallback v0.0.0-20250916063316-ddb4e80c6ad3/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18= +golang.org/x/crypto/x509roots/fallback v0.0.0-20250927194341-2beaa59a3c99 h1:CH0o4/bZX6KIUCjjgjmtNtfM/kXSkTYlzTOB9vZF45g= +golang.org/x/crypto/x509roots/fallback v0.0.0-20250927194341-2beaa59a3c99/go.mod h1:MEIPiCnxvQEjA4astfaKItNwEVZA5Ki+3+nyGbJ5N18= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6 h1:SbTAbRFnd5kjQXbczszQ0hdk3ctwYf3qBNH9jIsGclE= golang.org/x/exp v0.0.0-20250813145105-42675adae3e6/go.mod h1:4QTo5u+SEIbbKW1RacMZq1YEfOBqeXa19JeshGi+zc4= @@ -646,18 +646,18 @@ google.golang.org/genproto v0.0.0-20250603155806-513f23925822 h1:rHWScKit0gvAPuO google.golang.org/genproto v0.0.0-20250603155806-513f23925822/go.mod h1:HubltRL7rMh0LfnQPkMH4NPDFEWp0jw3vixw7jEM53s= google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5 h1:BIRfGDEjiHRrk0QKZe3Xv2ieMhtgRGeLcZQ0mIVn4EY= google.golang.org/genproto/googleapis/api v0.0.0-20250825161204-c5933d9347a5/go.mod h1:j3QtIyytwqGr1JUDtYXwtMXWPKsEa5LtzIFN1Wn5WvE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5 h1:eaY8u2EuxbRv7c3NiGK0/NedzVsCcV6hDuU5qPX5EGE= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250825161204-c5933d9347a5/go.mod h1:M4/wBTSeyLxupu3W3tJtOgB14jILAS/XWPSSa3TAlJc= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797 h1:CirRxTOwnRWVLKzDNrs0CXAaVozJoR4G9xvdRecrdpk= +google.golang.org/genproto/googleapis/rpc v0.0.0-20251002232023-7c0ddcbb5797/go.mod h1:HSkG/KdJWusxU1F6CNrwNDjBMgisKxGnc5dAZfT0mjQ= google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.75.0 h1:+TW+dqTd2Biwe6KKfhE5JpiYIBWq865PhKGSXiivqt4= -google.golang.org/grpc v1.75.0/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1 h1:F29+wU6Ee6qgu9TddPgooOdaqsxTMunOoj8KA5yuS5A= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.5.1/go.mod h1:5KF+wpkbTSbGcR9zteSqZV6fqFOWBl4Yde8En8MryZA= -google.golang.org/protobuf v1.36.8 h1:xHScyCOEuuwZEc6UtSOvPbAT4zRh0xcNRYekJwfqyMc= -google.golang.org/protobuf v1.36.8/go.mod h1:fuxRtAxBytpl4zzqUh6/eyUujkJdNiuEkXntxiD/uRU= +google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE= +google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=