package challenge import ( "testing" "time" ) func TestNewVerifier(t *testing.T) { config := TestConfig() verifier := NewVerifier(config) if verifier == nil { t.Fatal("expected verifier to be created") } if verifier.config != config { t.Error("expected verifier to store config reference") } } func TestVerifier_VerifyChallenge(t *testing.T) { config := TestConfig() generator := NewGenerator(config) verifier := NewVerifier(config) // Generate a valid challenge challenge, err := generator.GenerateChallenge() if err != nil { t.Fatalf("failed to generate challenge: %v", err) } // Verify the challenge err = verifier.VerifyChallenge(challenge) if err != nil { t.Fatalf("expected challenge verification to pass, got: %v", err) } } func TestVerifier_VerifyChallenge_Expired(t *testing.T) { config := TestConfig() verifier := NewVerifier(config) // Create an expired challenge expiredChallenge := &Challenge{ Timestamp: time.Now().Add(-10 * time.Minute).Unix(), // 10 minutes ago Difficulty: 4, Resource: "quotes", Random: []byte{0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6}, } expiredChallenge.Sign(config.HMACSecret) err := verifier.VerifyChallenge(expiredChallenge) if err != ErrExpiredChallenge { t.Fatalf("expected ErrExpiredChallenge, got: %v", err) } } func TestVerifier_VerifyChallenge_InvalidHMAC(t *testing.T) { config := TestConfig() verifier := NewVerifier(config) // Create a challenge with invalid HMAC challenge := &Challenge{ Timestamp: time.Now().Unix(), Difficulty: 4, Resource: "quotes", Random: []byte{0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6}, HMAC: []byte("invalid-hmac"), } err := verifier.VerifyChallenge(challenge) if err != ErrInvalidHMAC { t.Fatalf("expected ErrInvalidHMAC, got: %v", err) } } func TestVerifier_VerifyChallenge_TamperedChallenge(t *testing.T) { config := TestConfig() generator := NewGenerator(config) verifier := NewVerifier(config) // Generate a valid challenge challenge, err := generator.GenerateChallenge() if err != nil { t.Fatalf("failed to generate challenge: %v", err) } // Tamper with the challenge challenge.Difficulty = 10 // Verification should fail due to HMAC mismatch err = verifier.VerifyChallenge(challenge) if err != ErrInvalidHMAC { t.Fatalf("expected ErrInvalidHMAC for tampered challenge, got: %v", err) } } func TestVerifier_VerifyChallenge_DifferentSecret(t *testing.T) { config1 := TestConfig() config2 := TestConfig() // Different secret generator := NewGenerator(config1) verifier := NewVerifier(config2) // Generate challenge with config1 challenge, err := generator.GenerateChallenge() if err != nil { t.Fatalf("failed to generate challenge: %v", err) } // Try to verify with config2 (different secret) err = verifier.VerifyChallenge(challenge) if err != ErrInvalidHMAC { t.Fatalf("expected ErrInvalidHMAC with different secret, got: %v", err) } } func TestVerifier_VerifyChallenge_FutureTimestamp(t *testing.T) { config := TestConfig() verifier := NewVerifier(config) // Create a challenge with future timestamp futureChallenge := &Challenge{ Timestamp: time.Now().Add(10 * time.Minute).Unix(), // 10 minutes in future Difficulty: 4, Resource: "quotes", Random: []byte{0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6}, } futureChallenge.Sign(config.HMACSecret) // Future challenges should still be valid (not expired) err := verifier.VerifyChallenge(futureChallenge) if err != nil { t.Fatalf("expected future challenge to be valid, got: %v", err) } } func TestVerifier_VerifyChallenge_EmptyHMAC(t *testing.T) { config := TestConfig() verifier := NewVerifier(config) // Create a challenge without HMAC challenge := &Challenge{ Timestamp: time.Now().Unix(), Difficulty: 4, Resource: "quotes", Random: []byte{0xa1, 0xb2, 0xc3, 0xd4, 0xe5, 0xf6}, HMAC: nil, } err := verifier.VerifyChallenge(challenge) if err != ErrMalformedChallenge { t.Fatalf("expected ErrMalformedChallenge for empty HMAC, got: %v", err) } }