From 7b001d710a0e41c58ef3be994796432d44be9f46 Mon Sep 17 00:00:00 2001 From: eleksir Date: Sat, 4 Apr 2026 15:59:40 +0300 Subject: [PATCH] Implement timing-safe string comparison for authentication Prevents timing attacks where an attacker could deduce correct credentials by measuring response times. Not sure if it is real threat, but anyway. --- internal/backer/newServer.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/internal/backer/newServer.go b/internal/backer/newServer.go index c8669e1..6a1bca2 100644 --- a/internal/backer/newServer.go +++ b/internal/backer/newServer.go @@ -2,6 +2,7 @@ package backer import ( "context" + "crypto/subtle" "crypto/tls" "errors" "fmt" @@ -83,10 +84,8 @@ func NewServer(configPath string) (*ServerWrapper, error) { return } - // Both username AND password must match. Explicitly require that the whole condition - // fails when either is incorrect, per the authentication design. - //nolint:staticcheck // QF1001: De Morgan's law is irrelevant here. - if !(username == C.User && password == C.Password) { + // Both username AND password must match. Use timing-safe comparison to prevent timing attacks. + if !timingSafeMatch(username, C.User) || !timingSafeMatch(password, C.Password) { w.Header().Set("WWW-Authenticate", `Basic realm="restricted", charset="UTF-8"`) http.Error(w, "Unauthorized", http.StatusUnauthorized) @@ -321,4 +320,10 @@ func (sw *ServerWrapper) ServeTLS(certFile, keyFile string) error { return err } +// timingSafeMatch performs constant-time comparison to prevent timing attacks. +// Returns 1 if the strings are equal, 0 otherwise. +func timingSafeMatch(a, b string) bool { + return subtle.ConstantTimeCompare([]byte(a), []byte(b)) == 1 +} + /* vim: setlocal ft=go noet ai ts=4 sw=4 sts=4: */