package player // Regression: Argon2id parameters parsed from a stored hash must be bounded // before they reach argon2.IDKey. A hand-edited or corrupted account file // (e.g. argon2id:1:4294967295:...) must fail the check, not request a // multi-TiB allocation that kills the process. import ( "crypto/sha256" "encoding/base64" "encoding/hex" "testing" ) func TestCheckPasswordRejectsOutOfRangeArgonParams(t *testing.T) { // Enormous memory cost (0xFFFFFFFF KiB) with an otherwise well-formed // hash: must be rejected before hashing. huge := "argon2id:1:4294967295:2:AAAAAAAAAAAAAAAAAAAAAA:0011223344556677889900112233445566778899001122334455667788990011" if CheckPassword("pw", huge) { t.Fatal("out-of-range Argon2 memory cost was accepted") } // Negative values would wrap through uint32 under a naive conversion. negative := "argon2id:-1:-1:-1:AAAAAAAAAAAAAAAAAAAAAA:0011223344556677889900112233445566778899001122334455667788990011" if CheckPassword("pw", negative) { t.Fatal("negative Argon2 parameters were accepted") } // Absurd time cost is bounded too. slow := "argon2id:4294967295:65536:2:AAAAAAAAAAAAAAAAAAAAAA:0011223344556677889900112233445566778899001122334455667788990011" if CheckPassword("pw", slow) { t.Fatal("out-of-range Argon2 time cost was accepted") } } func TestCheckPasswordAcceptsNormalAndLegacyHashes(t *testing.T) { hashed, err := HashPassword("s3cret") if err != nil { t.Fatal(err) } if !CheckPassword("s3cret", hashed) { t.Fatal("valid Argon2id hash rejected") } if CheckPassword("wrong", hashed) { t.Fatal("wrong password accepted") } // Legacy single-pass sha256 hashes must keep verifying so old accounts // can still log in and be upgraded. salt := []byte("sixteen-byte-slt") sum := sha256.Sum256(append(append([]byte{}, salt...), []byte("pw")...)) legacy := "sha256:" + base64.RawStdEncoding.EncodeToString(salt) + ":" + hex.EncodeToString(sum[:]) if !CheckPassword("pw", legacy) { t.Fatal("legacy sha256 hash rejected") } if CheckPassword("nope", legacy) { t.Fatal("wrong password accepted against legacy sha256 hash") } if !NeedsRehash(legacy) { t.Fatal("legacy sha256 hash not flagged for rehash") } }