package auth import "testing" func TestHashVerifyRoundTrip(t *testing.T) { h, err := HashPassword("s3cret-pw") if err != nil { t.Fatal(err) } if h == "s3cret-pw" || len(h) < 20 { t.Fatalf("bad hash %q", h) } ok, err := VerifyPassword(h, "s3cret-pw") if err != nil || !ok { t.Fatalf("verify failed: %v %v", ok, err) } bad, _ := VerifyPassword(h, "wrong") if bad { t.Fatal("wrong password must not verify") } } func TestHashNonDeterministic(t *testing.T) { a, _ := HashPassword("same") b, _ := HashPassword("same") if a == b { t.Fatal("salt must randomize hash") } } func TestVerifyPasswordBadTimeDoesNotPanic(t *testing.T) { defer func() { if r := recover(); r != nil { t.Fatalf("VerifyPassword panicked: %v", r) } }() encoded := "$argon2id$v=19$m=65536,t=0,p=4$c29tZXNhbHRzb21lc2FsdA$c29tZWhhc2hzb21laGFzaA" ok, err := VerifyPassword(encoded, "anything") if err == nil { t.Fatal("expected error for t=0, got nil") } if ok { t.Fatal("expected ok=false for t=0") } } func TestVerifyPasswordBadThreadsDoesNotPanic(t *testing.T) { defer func() { if r := recover(); r != nil { t.Fatalf("VerifyPassword panicked: %v", r) } }() encoded := "$argon2id$v=19$m=65536,t=1,p=0$c29tZXNhbHRzb21lc2FsdA$c29tZWhhc2hzb21laGFzaA" ok, err := VerifyPassword(encoded, "anything") if err == nil { t.Fatal("expected error for p=0, got nil") } if ok { t.Fatal("expected ok=false for p=0") } } func TestVerifyPasswordUnsupportedVersion(t *testing.T) { encoded := "$argon2id$v=18$m=65536,t=1,p=4$c29tZXNhbHRzb21lc2FsdA$c29tZWhhc2hzb21laGFzaA" ok, err := VerifyPassword(encoded, "anything") if err == nil { t.Fatal("expected error for unsupported version, got nil") } if ok { t.Fatal("expected ok=false for unsupported version") } } func TestVerifyPasswordGarbageFormatDoesNotPanic(t *testing.T) { defer func() { if r := recover(); r != nil { t.Fatalf("VerifyPassword panicked: %v", r) } }() ok, err := VerifyPassword("notahash", "anything") if err == nil { t.Fatal("expected error for garbage format, got nil") } if ok { t.Fatal("expected ok=false for garbage format") } }