forgejo-runner-optimiser/internal/receiver/token.go

26 lines
1 KiB
Go
Raw Normal View History

// ABOUTME: HMAC-SHA256 token generation and validation for scoped push authentication.
// ABOUTME: Tokens are derived from a key + scope, enabling stateless validation without DB storage.
package receiver
import (
"crypto/hmac"
"crypto/sha256"
"crypto/subtle"
"encoding/hex"
)
// GenerateScopedToken computes an HMAC-SHA256 token scoped to a specific org/repo/workflow/job.
// The canonical input is "v1\x00<org>\x00<repo>\x00<workflow>\x00<job>".
func GenerateScopedToken(key, org, repo, workflow, job string) string {
mac := hmac.New(sha256.New, []byte(key))
mac.Write([]byte("v1\x00" + org + "\x00" + repo + "\x00" + workflow + "\x00" + job))
return hex.EncodeToString(mac.Sum(nil))
}
// ValidateScopedToken checks whether a token matches the expected HMAC for the given scope.
// Uses constant-time comparison to prevent timing attacks.
func ValidateScopedToken(key, token, org, repo, workflow, job string) bool {
expected := GenerateScopedToken(key, org, repo, workflow, job)
return subtle.ConstantTimeCompare([]byte(token), []byte(expected)) == 1
}