Beta OTT provider: Tata Play Smart
This record covers two app generations: the older com.ryzmedia.tatasky
509.0/894 installed on the A15, and the newer com.tataplay.livetv 1.0.10/101
artifact whose native Retrofit layer is recoverable.
Experimental backend status
The newer app’s verified Retrofit contracts are now implemented behind
tataplay = true / OPENSTREAM_TATAPLAY=true (legacy alias
JIOTV_TATAPLAY=true) as a diagnostic beta. No live
Tata Play request has been made by this implementation yet.
Implemented beta routes:
GET /api/tataplay/statusPOST /api/tataplay/login/sendOTPPOST /api/tataplay/login/verifyOTPPOST /api/tataplay/refreshPOST /api/tataplay/logoutGET /api/tataplay/catalogue-seedGET /api/tataplay/epgGET /api/tataplay/entitlementGET /api/tataplay/play/:id?contentType=LIVE
The beta persists a stable synthetic device identity because the server is not
running inside the Android APK. OTP/session credentials remain server-side.
The app’s device_details header is an opaque persisted string whose producer
was not recovered; the beta therefore sends the app’s observed missing-value
form (an empty string) instead of inventing an encoding.
The playback diagnostic returns only booleans/counts such as whether a
Widevine play URL, license URL or session ID was present; it never returns
those values. Tata Play is not added to ActiveProduct, playlists, shared
catalogues, /live, or the DRM/license proxy.
The channels/all contract exposes only ordered documentIds; no per-ID
hydration endpoint has been proven, so catalogue-seed deliberately does not
pretend they are channel objects. EPG date/timestamp encodings are also not
guessed: testers must pass the app-observed date, epgStartTime and
epgEndTime values.
1. Artifact identity (observed fact)
- File:
reverse-engineering/apps/com.ryzmedia.tatasky_509.0-894_4arch_….apkm(APKMirror APKM v5, 43 inventory nodes, all hash-verified). - SHA-256 (APKM):
ab9091ab2a3bb42eeb2be2b6c6e59cc799d17b6af852618c13d433b253b90e14 - base.apk SHA-256:
93cb824c…095ac3bd0(71,312,419 B). info.json: appTata Play Smart: 500+ Channels, packagecom.ryzmedia.tatasky, version509.0/ code894, minSdk 27 / targetSdk 36, archesarm64-v8a/armeabi-v7a/x86/x86_64, 7 dpis, 24 langs, leanback capable.- 12 DEX files (~106 MB); React Native + Hermes (
libhermes.so,assets/index.android.bundle12.2 MB, encrypted: magic05011cc1…, zero URLs, max printable run 16 chars); CodePush OTA.
1a. Static follow-up (JADX 1.5.6, full base.apk)
The earlier pass could not run JADX. This pass decompiled all 12 DEX files and re-inspected the bundle:
com/ryzmedia/tataskycontains onlyMainApplication,BuildConfig,R, UI/utility packages and SDK glue. There is no app-level Retrofit/OkHttp API class, no request builder, and no endpoint map anywhere in the DEX.BuildConfigexposesBASE_URL=https://tm.tapi.videoready.tv/,ACTION_NAME_CONFIG=rest-api/pub/api/v1/config,X_API_KEY,X_APP_ID=ott-app,X_APP_KEY,IRDETO_BASE_URL,CODEPUSH_SERVER_URL,BUNDLE_ID=com.hungama.tatasky. Nothing in the DEX consumesACTION_NAME_CONFIG; it is read from JS.MainApplicationusesDefaultReactNativeHost.getJSBundleFile()→CodePush.getJSBundleFile(), so the JS layer is the API layer.assets/index.android.bundleis encrypted, not Hermes bytecode: first bytes05 01 1c c1, noc6 1f bc 03magic anywhere in 12.2 MB, Shannon entropy 7.997 bits/byte, no readable strings, no ZIP/gzip container.- No AES key or bundle-decryption routine is reachable from the DEX: the app
classes are DexGuard-obfuscated and the only native crypto-capable libraries
are stock Hermes/React Native plus packed
libc2f2.so/libc7a509.so. A brute-force check of plausible keys derived from the BuildConfig values (raw/MD5/SHA-1/SHA-256, AES-CBC/ECB, several IV placements) produced no Hermes header or JS text.
Conclusion for the original com.ryzmedia.tatasky base artifact: no login,
catalogue, EPG, playback, license or subscription contract is statically
recoverable from its encrypted fallback bundle or DEX files. This historical
conclusion does not apply to the separate com.tataplay.livetv artifact below.
The diagnostic beta uses recovered contracts from that newer app and keeps Tata
Play out of the shared catalogue and shared playback paths.
1b. New artifact and runtime evidence (follow-up pass)
Two different Tata Play packages are now in scope:
- Installed, logged in on the A15:
com.ryzmedia.tatasky509.0/894 (this record’s original artifact). Its encrypted fallback bundle was bypassed legally by fetching the app’s own CodePush update with the deployment key embedded in the APK. The CodePush payload is a plain ZIP containing plain Hermes bytecode (index.android.bundle, 11.8 MB), so the real JS is recoverable. It exposes the full old-app API surface (login-service,rest-api,lit-mobile-common-bff,lit-subscription-service,pas/api/v1/access/control,content-detail, etc.) underhttps://tm.tapi.videoready.tv/. - New artifact in
TataPlay.zip: packagecom.tataplay.livetv(com.tataplaylit.tv, “Tata Play Smart”), with a native Retrofit API layer and a small RN subscription SDK. This is a different app generation; it is not the installed package.
Runtime boundary on the logged-in A15 (no subscription)
Observed through the device UI, without capturing tokens:
- Session restoration and home screen: work. The account is logged in.
- Channel catalogue / home rails: work (channels and “Subscribe” prompts).
- Live TV guide / EPG: work (programme rows, channel numbers, categories).
- Search: work (e.g. DD National HD, DD Sports HD, DD India HD).
- Premium live playback: gated by the app’s own “Subscribe” UI; the account has no active pack. No subscription was purchased or activated.
- Free-to-air playback was not conclusively triggered through ADB touch input (the leanback cards did not accept injected taps); therefore no claim is made that free channels play.
- No API request/response was captured: the release package is not debuggable, the device has no root, and the app does not trust user CAs, so TLS interception would require patching the app (not done). No OTP was entered by the agent.
New app static contracts (recovered, beta-enabled)
The new com.tataplay.livetv app has a native NetworkApi with explicit
Retrofit annotations on https://tm.tapi.videoready.tv/:
POST login-service/pub/api/v3/signin/generate/otp(GenerateBody{rmn,sid})POST login-service/pub/api/v3/signin/validate/otp(ValidateOtpPayLoad{…})POST rest-api/pub/api/v3/refreshToken(RefreshTokenRequest{refreshToken,subscriberId})GET lit-subscription-service/api/v1/lit/getEntitlementDetailsGET portal-search/pub/api/v1/channels/all?limit&offsetGET lit-mobile-common-bff/api/v2/channels/guide?…GET pas/api/v1/access/control/{contentType}/{channelId}→PlayUrlDataGET content-detail/pub/api/v3/catchupEpg/{channelId}?isLitEnabled=truePOST device-management/v1/app/lit/subscriber/{subscriberId}/device
Header injection is explicit (RD0 interceptor): Authorization: bearer <KS>,
appVersion: 1.0.10, platform, deviceId, device_details, deviceName,
x-device-id, x-subscriber-id, x-authenticated-userid, subscriberId,
sid, countryRegion, profileId. Token expiry is expiresIn (epoch millis
or duration) and refresh uses the refreshToken/subscriberId body.
These contracts are enabled only inside the isolated diagnostic beta. They
were recovered statically and still need runtime request/response proof. The
OTP implementation follows the app’s recovered payload construction, including
loginOption=OTP, the pending JWT, selectable LIT/DTH refId values, and
the observed refIdMode behavior. Analytics IDs are sent as empty strings
because no backend equivalent exists and the app does not prove they must be
non-empty.
2. API bases (observed static strings)
BASE_URL = https://tm.tapi.videoready.tv/(BASE_URL_CONFIG_AKAMAIsame;API_BASE_URL = ${BASE_URL}placeholder;API_TIMEOUT = 15000).CODEPUSH_SERVER_URL = https://cp.tapi.videoready.tv/.IRDETO_BASE_URL = https://tatasky-csm.live.ott.irdeto.com/(Irdeto CSM).- Hotstar/Bifrost stack embedded (analytics/player):
api/apix/hf-apix/pp-apix/ pp-hf-apix/bifrost-api*.hotstar.com. - No Tata Play content-endpoint paths (
/live,/epg,/channel,/catalog,/search,/vod, license URL) in ~1.2 M dex strings, 859 resources, or manifest (observed absence).
3. Auth (facts + gaps)
- Facts:
SmsBroadcastReceiver(OTP auto-read, Juspay SMS-handler), Facebook Login SDK, Google OAuth revoke URL, Firebase Auth/Messaging,EncryptSharedPreferencesmigration (tokens encrypted at rest), MoEngagesetMobileNumber(RMN = user identity), deeplinkstataplay://+https://a2uuh.app.goo.gl. - Unknown: OTP request/verify paths, token names/expiry/refresh, device binding (all behind the encrypted JS bundle).
4. Device identity (facts)
READ_PHONE_STATE(not required), AppsFlyer, MoEngage, Firebase (project_id=tata-sky-new-ott), Salesforce MarketingCloud, New Relic, Ad ID + AdServices. No static device-ID key names recovered.
5. Signing / hardening (facts)
- base.apk has no v1 JAR signature (v2/v3+ block present); bundle-tool
stamp-cert-sha256observed (value withheld per policy for cert digests? non-secret but omitted here). usesCleartextTraffic=false,allowBackup=false,extractNativeLibs=false;networkSecurityConfigdeclared but nonetwork_security_config.xmlin base.apk (likely in a split or stale). Pinning posture unknown.- DexGuard-style obfuscation (
o.*,libc2f2.so/libc7a509.so), Play Integrity refs,DETECT_SCREEN_RECORDING.
6–8. Subscription / catalogue / EPG / VOD
- Facts: Juspay HyperSDK (UPI/cards),
CHECK_LICENSE(Play license). - No pack/entitlement, channel-list, EPG, search, VOD, or catch-up endpoints
visible statically. One lead: Hotstar JHS media SDK + live-player
default_config.json→ Hotstar-derived playback stack. - Lineage string:
BUNDLE_ID = com.hungama.tatasky(Hungama white-label). - Manifest: 49 activities, 35 services, 28 receivers, 15 providers; PiP, foreground-service playback, exact-alarm + timezone/boot receivers (schedule-aware, not proof of EPG source).
9. Playback + DRM (facts + unknown)
- Facts: dual ExoPlayer (
androidx.media3+ vendoredcom.jhs.media…),ExoDownloadServiceCore(offline), IMA + SSAI, Cast. - DRM: Media3
DefaultDrmSession*+MediaDrm; DRM error strings; Irdeto CSM suggests multi-DRM/license via Irdeto; PlayReadyAcquireLicenseis an ExoPlayer constant, not proof of use. - Unknown: Widevine license URL, key-system flow (expected behind encrypted bundle + Irdeto CSM at runtime).
10. Runtime gaps
MITM capture (device + user OTP) against tm.tapi.videoready.tv and Irdeto
CSM; decrypt/unpack index.android.bundle or CodePush update; JADX setup;
pinning + full cert chain. Backend implements device/token persistence,
generic OTP/login/catalogue/playback/license contracts with mock tests, and
marks content paths as unresolved.