diff options
| author | historia <[not public]> | 2026-09-19 03:15:59 -0400 |
|---|---|---|
| committer | historia <[not public]> | 2026-09-19 03:15:59 -0400 |
| commit | 0e60567a7a0addb9421769ee7be7853bfa8788cb (patch) | |
| tree | 7645112db0e4eae95b8a83c1e4f9aab38bede655 /internal/player/password.go | |
| parent | cc33072eced3d5460512c09c42ec4531c807d7af (diff) | |
| download | thehouseoficarus-0e60567a7a0addb9421769ee7be7853bfa8788cb.tar.gz | |
refactor: simplifcation, change how rooms are stored in player yaml, remove legacy code
Diffstat (limited to 'internal/player/password.go')
| -rw-r--r-- | internal/player/password.go | 77 |
1 files changed, 25 insertions, 52 deletions
diff --git a/internal/player/password.go b/internal/player/password.go index de5fe5f..706ef45 100644 --- a/internal/player/password.go +++ b/internal/player/password.go @@ -2,7 +2,6 @@ package player import ( "crypto/rand" - "crypto/sha256" "crypto/subtle" "encoding/base64" "encoding/hex" @@ -19,10 +18,8 @@ import ( // // argon2id:<time>:<memoryKiB>:<threads>:<b64salt>:<hexkey> // -// Legacy accounts may still carry the old single-pass salted SHA-256 hash -// ("sha256:<b64salt>:<hexhash>"); CheckPassword verifies both, and the -// login paths rehash to Argon2id on successful verification (see -// NeedsRehash). +// Only Argon2id is accepted: the prototype has no password-hash migration and +// accounts are recreated rather than upgraded. const ( argonTime = 1 argonMemory = 64 * 1024 // KiB @@ -78,57 +75,33 @@ func HashPassword(password string) (string, error) { base64.RawStdEncoding.EncodeToString(salt), hex.EncodeToString(key)), nil } -// CheckPassword verifies a password against a stored hash in either the -// current Argon2id format or the legacy salted SHA-256 format. +// CheckPassword verifies a password against a stored Argon2id hash. func CheckPassword(password, stored string) bool { parts := strings.SplitN(stored, ":", 6) - if len(parts) == 0 { + if len(parts) == 0 || parts[0] != "argon2id" { return false } - switch parts[0] { - case "argon2id": - if len(parts) != 6 { - return false - } - t, errT := strconv.Atoi(parts[1]) - m, errM := strconv.Atoi(parts[2]) - p, errP := strconv.Atoi(parts[3]) - salt, errSalt := base64.RawStdEncoding.DecodeString(parts[4]) - expected, errKey := hex.DecodeString(parts[5]) - if errT != nil || errM != nil || errP != nil || errSalt != nil || errKey != nil { - return false - } - if t < argonMinTime || t > argonMaxTime || - m < argonMinMemory || m > argonMaxMemory || - p < argonMinThreads || p > argonMaxThreads || - len(expected) < argonMinKeyLen || len(expected) > argonMaxKeyLen { - // Out-of-range parameters: fail the check instead of trusting the - // stored values and requesting an enormous allocation. - return false - } - acquireHashSlot() - key := argon2.IDKey([]byte(password), salt, uint32(t), uint32(m), uint8(p), uint32(len(expected))) - releaseHashSlot() - return subtle.ConstantTimeCompare(key, expected) == 1 - case "sha256": - legacy := strings.SplitN(stored, ":", 3) - if len(legacy) != 3 { - return false - } - salt, err := base64.RawStdEncoding.DecodeString(legacy[1]) - if err != nil { - return false - } - hash := sha256.Sum256(append(salt, []byte(password)...)) - return subtle.ConstantTimeCompare([]byte(legacy[2]), []byte(fmt.Sprintf("%x", hash))) == 1 - default: + if len(parts) != 6 { return false } -} - -// NeedsRehash reports whether a stored hash uses the legacy single-pass -// SHA-256 scheme. Callers rehash with HashPassword after a successful -// verification and persist the new hash (transparent upgrade on login). -func NeedsRehash(stored string) bool { - return strings.HasPrefix(stored, "sha256:") + t, errT := strconv.Atoi(parts[1]) + m, errM := strconv.Atoi(parts[2]) + p, errP := strconv.Atoi(parts[3]) + salt, errSalt := base64.RawStdEncoding.DecodeString(parts[4]) + expected, errKey := hex.DecodeString(parts[5]) + if errT != nil || errM != nil || errP != nil || errSalt != nil || errKey != nil { + return false + } + if t < argonMinTime || t > argonMaxTime || + m < argonMinMemory || m > argonMaxMemory || + p < argonMinThreads || p > argonMaxThreads || + len(expected) < argonMinKeyLen || len(expected) > argonMaxKeyLen { + // Out-of-range parameters: fail the check instead of trusting the + // stored values and requesting an enormous allocation. + return false + } + acquireHashSlot() + key := argon2.IDKey([]byte(password), salt, uint32(t), uint32(m), uint8(p), uint32(len(expected))) + releaseHashSlot() + return subtle.ConstantTimeCompare(key, expected) == 1 } |
