25 lines
1 KiB
Go
25 lines
1 KiB
Go
// 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
|
|
}
|