155 lines
4 KiB
Go
155 lines
4 KiB
Go
|
|
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)
|
||
|
|
}
|
||
|
|
}
|