ai-code-battle/starters/go/game/auth.go
jedarden 7694723758 feat(starter-go): implement Go starter kit with shared game package
Complete Go starter kit for AI Code Battle with:

- main.go: HTTP server with HMAC authentication, placeholder computeMoves()
- game/ package: Shared utilities (types, auth, grid) for reuse
  - types.go: Game state types, Direction constants, Position, etc.
  - auth.go: HMAC-SHA256 signing/verification with timestamp validation
  - grid.go: Toroidal distance, BFS pathfinding, neighbor functions
- Tests: Comprehensive test coverage for grid and auth utilities
- Dockerfile: Multi-stage build with Go 1.24-alpine
- README: Complete documentation with examples and protocol reference

The starter kit provides a minimal working bot that holds position
by default. Participants implement their strategy in computeMoves()
using the provided grid utilities.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-05-08 10:10:51 -04:00

48 lines
1.3 KiB
Go

// Package game provides authentication utilities for AI Code Battle bots.
package game
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"fmt"
"strconv"
)
// VerifyRequest verifies the HMAC signature of an incoming request.
func VerifyRequest(secret string, headers AuthHeaders, body []byte) bool {
// Verify timestamp is within allowed window
if headers.Timestamp != "" && !VerifyTimestamp(headers.Timestamp) {
return false
}
// Compute expected signature
bodyHash := sha256.Sum256(body)
signingString := fmt.Sprintf("%s.%s.%s.%s",
headers.MatchID,
headers.Turn,
headers.Timestamp,
hex.EncodeToString(bodyHash[:]))
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(signingString))
expectedSig := hex.EncodeToString(mac.Sum(nil))
// Constant-time comparison to prevent timing attacks
return hmac.Equal([]byte(headers.Signature), []byte(expectedSig))
}
// SignResponse generates the HMAC signature for a response.
func SignResponse(secret, matchID, turnStr string, body []byte) string {
bodyHash := sha256.Sum256(body)
turn, _ := strconv.Atoi(turnStr)
signingString := fmt.Sprintf("%s.%d.%s",
matchID,
turn,
hex.EncodeToString(bodyHash[:]))
mac := hmac.New(sha256.New, []byte(secret))
mac.Write([]byte(signingString))
return hex.EncodeToString(mac.Sum(nil))
}