package office import ( "crypto/hmac" "crypto/sha256" "encoding/base64" "encoding/json" "fmt" ) func signJWT(payload any, secret string) (string, error) { if secret == "" { return "", nil } header := base64.RawURLEncoding.EncodeToString([]byte(`{"alg":"HS256","typ":"JWT"}`)) bodyBytes, err := json.Marshal(payload) if err != nil { return "", err } body := base64.RawURLEncoding.EncodeToString(bodyBytes) mac := hmac.New(sha256.New, []byte(secret)) _, _ = mac.Write([]byte(header + "." + body)) sig := base64.RawURLEncoding.EncodeToString(mac.Sum(nil)) return header + "." + body + "." + sig, nil } func wrapConfig(config map[string]any, secret string) (map[string]any, error) { if secret == "" { return config, nil } token, err := signJWT(config, secret) if err != nil { return nil, err } config["token"] = token return config, nil } func verifyJWT(token, secret string) (map[string]any, error) { if secret == "" || token == "" { return nil, fmt.Errorf("missing token or secret") } parts := splitJWT(token) if len(parts) != 3 { return nil, fmt.Errorf("invalid token") } mac := hmac.New(sha256.New, []byte(secret)) _, _ = mac.Write([]byte(parts[0] + "." + parts[1])) expected := base64.RawURLEncoding.EncodeToString(mac.Sum(nil)) if !hmac.Equal([]byte(expected), []byte(parts[2])) { return nil, fmt.Errorf("invalid signature") } raw, err := base64.RawURLEncoding.DecodeString(parts[1]) if err != nil { return nil, err } var payload map[string]any if err := json.Unmarshal(raw, &payload); err != nil { return nil, err } return payload, nil } func splitJWT(token string) []string { var parts []string start := 0 for i := 0; i < len(token); i++ { if token[i] == '.' { parts = append(parts, token[start:i]) start = i + 1 } } parts = append(parts, token[start:]) return parts }