Something went wrong. Try again.
This repository has no description
Something went wrong. Try again.
2.5 kB · 81 lines
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182package spxrpc
import ( "context" "crypto/hmac" "crypto/sha256" "encoding/base64" "fmt" "strconv" "strings" "time")
// Pre-live HLS playback tokens. HLS requests carry no session, so a streamer// previewing their own unpublished stream over HLS proves who they are with// a token minted through the authenticated getLiveToken query: the DID and// an expiry, HMAC-signed with a key shared through statedb (so// every node in a station honours it).
const liveTokenTTL = time.Hour
// liveTokenKey is the station's token key, read from statedb once: token// checks happen on every pre-live playlist and segment request, and the key// never changes once it exists.func (s *Server) liveTokenKey(ctx context.Context) ([]byte, error) { if key := s.liveTokenKeyCache.Load(); key != nil { return *key, nil } if s.statefulDB == nil { return nil, fmt.Errorf("no statedb") } key, err := s.statefulDB.EnsureLiveTokenKey(ctx) if err != nil { return nil, err } s.liveTokenKeyCache.Store(&key) return key, nil}
func liveTokenSig(key []byte, did string, exp int64) string { mac := hmac.New(sha256.New, key) mac.Write([]byte(did + "\x00" + strconv.FormatInt(exp, 10))) return base64.RawURLEncoding.EncodeToString(mac.Sum(nil))}
// mintLiveToken returns a token for did valid until the returned time.func mintLiveToken(key []byte, did string, now time.Time) (string, time.Time) { exp := now.Add(liveTokenTTL).Unix() tok := "v1." + base64.RawURLEncoding.EncodeToString([]byte(did)) + "." + strconv.FormatInt(exp, 10) + "." + liveTokenSig(key, did, exp) return tok, time.Unix(exp, 0)}
// verifyLiveToken reports whether token was minted for did and is unexpired.func verifyLiveToken(key []byte, token, did string, now time.Time) bool { parts := strings.Split(token, ".") if len(parts) != 4 || parts[0] != "v1" { return false } rawDID, err := base64.RawURLEncoding.DecodeString(parts[1]) if err != nil || string(rawDID) != did { return false } exp, err := strconv.ParseInt(parts[2], 10, 64) if err != nil || now.Unix() > exp { return false } return hmac.Equal([]byte(parts[3]), []byte(liveTokenSig(key, did, exp)))}
// liveTokenAllows reports whether token lets the caller watch did's// unpublished stream.func (s *Server) liveTokenAllows(ctx context.Context, token, did string) bool { if token == "" { return false } key, err := s.liveTokenKey(ctx) if err != nil { return false } return verifyLiveToken(key, token, did, time.Now())}