chore: establish local platform baseline

This commit is contained in:
Codex Local
2026-08-26 06:41:54 +08:00
commit 29bdf4900f
575 changed files with 95644 additions and 0 deletions
+72
View File
@@ -0,0 +1,72 @@
package rtc
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/json"
"errors"
"strings"
"time"
)
type TokenClaims struct {
Version int `json:"v"`
RoomID string `json:"room_id"`
UserID string `json:"user_id"`
ExpiresAt int64 `json:"exp"`
}
type TokenIssuer interface {
Issue(roomID, userID string, expiresAt time.Time) (string, error)
}
type LocalTokenIssuer struct{ secret []byte }
func NewLocalTokenIssuer(secret []byte) (*LocalTokenIssuer, error) {
if len(secret) < 32 {
return nil, errors.New("RTC token signing secret must contain at least 32 bytes")
}
return &LocalTokenIssuer{secret: append([]byte(nil), secret...)}, nil
}
func (i *LocalTokenIssuer) Issue(roomID, userID string, expiresAt time.Time) (string, error) {
if roomID == "" || userID == "" || expiresAt.IsZero() {
return "", errors.New("room, user and expiry are required")
}
payload, err := json.Marshal(TokenClaims{Version: 1, RoomID: roomID, UserID: userID, ExpiresAt: expiresAt.Unix()})
if err != nil {
return "", err
}
encoded := base64.RawURLEncoding.EncodeToString(payload)
return "dev1." + encoded + "." + base64.RawURLEncoding.EncodeToString(i.sign(encoded)), nil
}
func (i *LocalTokenIssuer) Verify(token string, now time.Time) (TokenClaims, error) {
parts := strings.Split(token, ".")
if len(parts) != 3 || parts[0] != "dev1" {
return TokenClaims{}, errors.New("invalid RTC token")
}
signature, err := base64.RawURLEncoding.DecodeString(parts[2])
if err != nil || !hmac.Equal(signature, i.sign(parts[1])) {
return TokenClaims{}, errors.New("invalid RTC token")
}
payload, err := base64.RawURLEncoding.DecodeString(parts[1])
if err != nil {
return TokenClaims{}, errors.New("invalid RTC token")
}
var claims TokenClaims
if err := json.Unmarshal(payload, &claims); err != nil || claims.Version != 1 || claims.RoomID == "" || claims.UserID == "" {
return TokenClaims{}, errors.New("invalid RTC token")
}
if now.Unix() >= claims.ExpiresAt {
return TokenClaims{}, errors.New("RTC token expired")
}
return claims, nil
}
func (i *LocalTokenIssuer) sign(payload string) []byte {
mac := hmac.New(sha256.New, i.secret)
_, _ = mac.Write([]byte(payload))
return mac.Sum(nil)
}
+29
View File
@@ -0,0 +1,29 @@
package rtc
import (
"testing"
"time"
)
func TestLocalTokenIsDeterministicBoundAndExpiring(t *testing.T) {
issuer, err := NewLocalTokenIssuer([]byte("01234567890123456789012345678901"))
if err != nil {
t.Fatal(err)
}
expiresAt := time.Unix(2_000_000_000, 0)
first, _ := issuer.Issue("room-1", "device-user-1", expiresAt)
second, _ := issuer.Issue("room-1", "device-user-1", expiresAt)
if first != second {
t.Fatal("same claims must regenerate the same token for idempotent replay")
}
claims, err := issuer.Verify(first, expiresAt.Add(-time.Second))
if err != nil || claims.RoomID != "room-1" || claims.UserID != "device-user-1" {
t.Fatalf("claims = %#v, err = %v", claims, err)
}
if _, err := issuer.Verify(first, expiresAt); err == nil {
t.Fatal("expired token was accepted")
}
if _, err := issuer.Verify(first+"x", expiresAt.Add(-time.Second)); err == nil {
t.Fatal("tampered token was accepted")
}
}
+117
View File
@@ -0,0 +1,117 @@
package rtc
import (
"bytes"
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"errors"
"fmt"
"math"
"time"
)
const volcengineTokenVersion = "001"
// VolcengineTokenIssuer creates the production RTC token format documented by
// Volcengine. The issuer is deterministic for a room/user/expiry tuple so an
// idempotent API replay can reconstruct the same short-lived credential
// without persisting it.
type VolcengineTokenIssuer struct {
appID string
appKey []byte
ttl time.Duration
}
func NewVolcengineTokenIssuer(appID, appKey string, ttl time.Duration) (*VolcengineTokenIssuer, error) {
if len(appID) != 24 {
return nil, errors.New("Volcengine RTC app ID must contain exactly 24 characters")
}
if len(appKey) < 16 {
return nil, errors.New("Volcengine RTC app key must contain at least 16 characters")
}
if ttl <= 0 {
return nil, errors.New("Volcengine RTC token TTL must be positive")
}
return &VolcengineTokenIssuer{appID: appID, appKey: []byte(appKey), ttl: ttl}, nil
}
func (i *VolcengineTokenIssuer) Issue(roomID, userID string, expiresAt time.Time) (string, error) {
if roomID == "" || userID == "" || expiresAt.IsZero() {
return "", errors.New("room, user and expiry are required")
}
issuedAt := expiresAt.Add(-i.ttl).Unix()
expiresUnix := expiresAt.Unix()
if issuedAt < 0 || issuedAt > math.MaxUint32 || expiresUnix <= issuedAt || expiresUnix > math.MaxUint32 {
return "", errors.New("RTC token issue and expiry times must fit unsigned 32-bit Unix timestamps")
}
message := bytes.NewBuffer(nil)
nonce := i.nonce(roomID, userID, uint32(expiresUnix))
writeUint32(message, nonce)
writeUint32(message, uint32(issuedAt))
writeUint32(message, uint32(expiresUnix))
if err := writeString(message, roomID); err != nil {
return "", fmt.Errorf("encode RTC room ID: %w", err)
}
if err := writeString(message, userID); err != nil {
return "", fmt.Errorf("encode RTC user ID: %w", err)
}
// Privilege 0 expands to publish audio/video/data (1/2/3); privilege 4
// permits subscription. All privileges expire with the token itself.
privileges := []uint16{0, 1, 2, 3, 4}
writeUint16(message, uint16(len(privileges)))
for _, privilege := range privileges {
writeUint16(message, privilege)
writeUint32(message, uint32(expiresUnix))
}
mac := hmac.New(sha256.New, i.appKey)
_, _ = mac.Write(message.Bytes())
signature := mac.Sum(nil)
content := bytes.NewBuffer(nil)
if err := writeBytes(content, message.Bytes()); err != nil {
return "", err
}
if err := writeBytes(content, signature); err != nil {
return "", err
}
return volcengineTokenVersion + i.appID + base64.StdEncoding.EncodeToString(content.Bytes()), nil
}
func (i *VolcengineTokenIssuer) nonce(roomID, userID string, expiresAt uint32) uint32 {
mac := hmac.New(sha256.New, i.appKey)
_, _ = mac.Write([]byte("rtc-token-nonce\x00" + roomID + "\x00" + userID + "\x00"))
var expiry [4]byte
binary.LittleEndian.PutUint32(expiry[:], expiresAt)
_, _ = mac.Write(expiry[:])
return binary.LittleEndian.Uint32(mac.Sum(nil)[:4])
}
func writeUint16(buffer *bytes.Buffer, value uint16) {
var encoded [2]byte
binary.LittleEndian.PutUint16(encoded[:], value)
_, _ = buffer.Write(encoded[:])
}
func writeUint32(buffer *bytes.Buffer, value uint32) {
var encoded [4]byte
binary.LittleEndian.PutUint32(encoded[:], value)
_, _ = buffer.Write(encoded[:])
}
func writeString(buffer *bytes.Buffer, value string) error {
return writeBytes(buffer, []byte(value))
}
func writeBytes(buffer *bytes.Buffer, value []byte) error {
if len(value) > math.MaxUint16 {
return errors.New("RTC token field exceeds 65535 bytes")
}
writeUint16(buffer, uint16(len(value)))
_, _ = buffer.Write(value)
return nil
}
+88
View File
@@ -0,0 +1,88 @@
package rtc
import (
"crypto/hmac"
"crypto/sha256"
"encoding/base64"
"encoding/binary"
"strings"
"testing"
"time"
)
func TestVolcengineTokenIssuerProducesSignedScopedDeterministicToken(t *testing.T) {
const appID = "661e7ae5543cf00000000000"
appKey := "unit-test-" + strings.Repeat("x", 23)
issuer, err := NewVolcengineTokenIssuer(appID, appKey, 5*time.Minute)
if err != nil {
t.Fatal(err)
}
expiresAt := time.Unix(1_800_000_000, 0).UTC()
first, err := issuer.Issue("room-1", "device-1", expiresAt)
if err != nil {
t.Fatal(err)
}
second, err := issuer.Issue("room-1", "device-1", expiresAt)
if err != nil || second != first {
t.Fatalf("idempotent issue mismatch: err=%v equal=%v", err, second == first)
}
if len(first) <= 27 || first[:27] != "001"+appID {
t.Fatalf("unexpected token prefix: %q", first)
}
content, err := base64.StdEncoding.DecodeString(first[27:])
if err != nil {
t.Fatal(err)
}
message, rest := readTokenBytes(t, content)
signature, rest := readTokenBytes(t, rest)
if len(rest) != 0 {
t.Fatalf("unexpected trailing token bytes: %d", len(rest))
}
mac := hmac.New(sha256.New, []byte(appKey))
_, _ = mac.Write(message)
if !hmac.Equal(signature, mac.Sum(nil)) {
t.Fatal("token signature is invalid")
}
offset := 4 // deterministic nonce
issuedAt := binary.LittleEndian.Uint32(message[offset : offset+4])
offset += 4
expires := binary.LittleEndian.Uint32(message[offset : offset+4])
offset += 4
room, remaining := readTokenBytes(t, message[offset:])
user, remaining := readTokenBytes(t, remaining)
if string(room) != "room-1" || string(user) != "device-1" || issuedAt != uint32(expiresAt.Add(-5*time.Minute).Unix()) || expires != uint32(expiresAt.Unix()) {
t.Fatalf("unexpected token scope room=%s user=%s issued=%d expires=%d", room, user, issuedAt, expires)
}
if len(remaining) != 2+5*6 || binary.LittleEndian.Uint16(remaining[:2]) != 5 {
t.Fatalf("unexpected privileges payload: %x", remaining)
}
for index, want := range []uint16{0, 1, 2, 3, 4} {
position := 2 + index*6
if got := binary.LittleEndian.Uint16(remaining[position : position+2]); got != want {
t.Fatalf("privilege[%d]=%d want=%d", index, got, want)
}
if got := binary.LittleEndian.Uint32(remaining[position+2 : position+6]); got != uint32(expiresAt.Unix()) {
t.Fatalf("privilege[%d] expiry=%d", index, got)
}
}
}
func TestVolcengineTokenIssuerValidatesApplicationIdentity(t *testing.T) {
if _, err := NewVolcengineTokenIssuer("short", "0123456789abcdef", time.Minute); err == nil {
t.Fatal("expected invalid app ID to be rejected")
}
}
func readTokenBytes(t *testing.T, input []byte) ([]byte, []byte) {
t.Helper()
if len(input) < 2 {
t.Fatal("truncated token field length")
}
length := int(binary.LittleEndian.Uint16(input[:2]))
if len(input) < 2+length {
t.Fatal("truncated token field")
}
return input[2 : 2+length], input[2+length:]
}