Skip to content

Commit

Permalink
caddyauth: Speed up basicauth provisioning, precalculate fake password
Browse files Browse the repository at this point in the history
  • Loading branch information
francislavoie committed Apr 22, 2022
1 parent db62942 commit 161d6f6
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 2 deletions.
6 changes: 4 additions & 2 deletions modules/caddyhttp/caddyauth/basicauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func (hba *HTTPBasicAuth) Provision(ctx caddy.Context) error {

// if supported, generate a fake password we can compare against if needed
if hasher, ok := hba.Hash.(Hasher); ok {
hba.fakePassword, err = hasher.Hash([]byte("antitiming"), []byte("fakesalt"))
hba.fakePassword = hasher.FakeHash()
if err != nil {
return fmt.Errorf("generating anti-timing password hash: %v", err)
}
Expand Down Expand Up @@ -271,9 +271,11 @@ type Comparer interface {
// that require a salt). Hashing modules which implement
// this interface can be used with the hash-password
// subcommand as well as benefitting from anti-timing
// features.
// features. A hasher also returns a fake hash which
// can be used for timing side-channel mitigation.
type Hasher interface {
Hash(plaintext, salt []byte) ([]byte, error)
FakeHash() []byte
}

// Account contains a username, password, and salt (if applicable).
Expand Down
17 changes: 17 additions & 0 deletions modules/caddyhttp/caddyauth/hashes.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ package caddyauth

import (
"crypto/subtle"
"encoding/base64"

"github.com/caddyserver/caddy/v2"
"golang.org/x/crypto/bcrypt"
Expand Down Expand Up @@ -55,6 +56,14 @@ func (BcryptHash) Hash(plaintext, _ []byte) ([]byte, error) {
return bcrypt.GenerateFromPassword(plaintext, 14)
}

// FakeHash returns a fake hash.
func (BcryptHash) FakeHash() []byte {
// hashed with the following command:
// caddy hash-password --plaintext "antitiming" --algorithm "bcrypt"
bytes, _ := base64.StdEncoding.DecodeString("JDJhJDE0JFgzdWxxZi9pR3huZjFrNm9NWi5SWmVKVW9xSTlQWDJQTTRyUzVsa0lLSlhkdUxHWEdQcnQ2")
return bytes
}

// ScryptHash implements the scrypt KDF as a hash.
type ScryptHash struct {
// scrypt's N parameter. If unset or 0, a safe default is used.
Expand Down Expand Up @@ -123,6 +132,14 @@ func (s ScryptHash) Hash(plaintext, salt []byte) ([]byte, error) {
return scrypt.Key(plaintext, salt, s.N, s.R, s.P, s.KeyLength)
}

// FakeHash returns a fake hash.
func (ScryptHash) FakeHash() []byte {
// hashed with the following command:
// caddy hash-password --plaintext "antitiming" --salt "fakesalt" --algorithm "scrypt"
bytes, _ := base64.StdEncoding.DecodeString("kFbjiVemlwK/ZS0tS6/UQqEDeaNMigyCs48KEsGUse8=")
return bytes
}

func hashesMatch(pwdHash1, pwdHash2 []byte) bool {
return subtle.ConstantTimeCompare(pwdHash1, pwdHash2) == 1
}
Expand Down

0 comments on commit 161d6f6

Please sign in to comment.