Files
CosmicClash/server/domain/join_auth.go
T
2026-08-31 21:44:27 +01:00

38 lines
1.4 KiB
Go

package domain
import (
"fmt"
"time"
)
// SignedJoinAuthorisation is the transport envelope. The signing primitive is
// supplied by the backend signer so this policy stays independent of key
// storage and cryptographic algorithm choice.
type SignedJoinAuthorisation struct {
Authorisation JoinAuthorisation
Signature []byte
}
func JoinAuthorisationBytes(auth JoinAuthorisation) []byte {
return []byte(fmt.Sprintf("%s\x00%s\x00%s\x00%s\x00%d\x00%d\x00%s\x00%d\x00%s",
auth.MatchID, auth.ServerID, auth.PlayerID, auth.SteamID, auth.Slot, auth.Team, auth.Protocol, auth.Generation, auth.ExpiresAt.UTC().Format(time.RFC3339Nano)))
}
func SignJoinAuthorisation(auth JoinAuthorisation, sign func([]byte) ([]byte, error)) (SignedJoinAuthorisation, error) {
if sign == nil {
return SignedJoinAuthorisation{}, ErrJoinAuthorisation
}
signature, err := sign(JoinAuthorisationBytes(auth))
if err != nil || len(signature) == 0 {
return SignedJoinAuthorisation{}, ErrJoinAuthorisation
}
return SignedJoinAuthorisation{Authorisation: auth, Signature: append([]byte(nil), signature...)}, nil
}
func (r *RankedConnections) AdmitSigned(signed SignedJoinAuthorisation, verify func([]byte, []byte) bool, now time.Time) (uint64, error) {
if len(signed.Signature) == 0 || verify == nil || !verify(JoinAuthorisationBytes(signed.Authorisation), signed.Signature) {
return 0, ErrJoinAuthorisation
}
return r.Admit(signed.Authorisation, now)
}