Sign in to myTeamSpeak and import what the account synchronises

The myTeamSpeak client protocol and its end-to-end encryption are
reverse-engineered (docs/myteamspeak): an HTTP POST of a framed protobuf,
a PBKDF2-HMAC-SHA512 login token and account key, an AES-GCM wrapped
item key and AES-CTR items with a SHA-512 trailer.

Options on desktop and Settings on Android gain a myTeamSpeak page: sign
in and out, and the account's bookmarks and identities, each picked for
import and marked when already here. The client stays signed in the way
the official one does, keeping the derived token and key rather than the
password; each read signs in afresh, and a sign-in the server no longer
takes signs out. Nothing is written to the account.

Items are the same Item_Data as the local TeamSpeak store, so they go
through the existing decoder and importer; a bookmark chosen alone brings
the identity it connects with, found by UUID or, as some name it, by
the identity's name.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-09-26 01:07:17 +00:00
parent 73a15a8cfc
commit a7aa122728
25 changed files with 3425 additions and 32 deletions

View File

@@ -0,0 +1,48 @@
# myTeamSpeak in the client
What is implemented, and what two-way sync would still need.
## Sign-in and read-only import (done)
`core/src/main/java/com/ts3client/myts/` — pure Java, no Swing/Android dependency, and no JDK API
that Android 13 lacks (hence `HttpURLConnection`, not `java.net.http`).
- `MyTeamSpeakLogin` — the account the client stays signed in to. Like the official client's
`Account_Data` (which stores email, the login token in its `password` field, and the account key as
`encryption_password`), it keeps `MyTeamSpeak.Credentials` — email, login token, account key — in the
private profile file `myteamspeak.properties`; never the password. `signIn` derives them, reads the
account and only then saves them; `fetch` reads the account again with the saved ones; `signOut`
deletes the file. When the server rejects saved credentials (`ERROR_LOGIN_FAILED`, e.g. the password
was changed elsewhere) `fetch` signs out.
- `MyTeamSpeak.download(Credentials)` — signs in (`authentication/login`), unwraps the item key, pulls
BOOKMARK, IDENTITY and ITEM_FOLDER with one `synchronization/requestServerItems` against an empty
local state (all-zero global and class versions, no details), decrypts every item, then ends the
session (`authentication/deleteSession`). Each read signs in afresh; no server session is kept.
- `MyTsCrypto` — PBKDF2-HMAC-SHA512 login token and account key, `LoginSession.key` unwrap (AES-256-GCM),
item frame decryption (little-endian AES-CTR + SHA-512 trailer). See `CRYPTO_RE_SALT.md`.
- `MyTsTransport` — the `application/ts3cloud` framing over HTTP/1.1; an interface so tests replay a server.
- Decrypted items are plain `Item_Data`, decoded by `teamspeak/SyncItemDecoder`. `TeamSpeakImporter`
gains `importSelected(all, chosen)` (chosen bookmarks bring the identities they use) and
`isPresent(item)`; the policy is the local settings.db import's: additive and idempotent.
Frontends: Swing Options → "myTeamSpeak" tab (`MyTeamSpeakPanel`); Android Settings → Account →
myTeamSpeak (`ui/MyTeamSpeakScreen.kt`). Both: sign in/out, the account's bookmarks and identities with a
checkbox each and whether they are imported already, Refresh, "Import selected".
Observed on the live account: a bookmark may name its identity by the identity's *name* ("Default") instead
of its item UUID; the importer resolves both.
Tests: `MyTsCryptoTest` (captured vectors), `MyTeamSpeakTest` (download against a replayed server built from
the captured login and item), `MyTeamSpeakLoginTest` (persistence, failed sign-in, rejected credentials).
## Two-way sync (not done)
Would additionally need the server's global and per-class version cursors and each item's
`item_uuid`/`sync_version_uuid` persisted, and a mapping between our bookmarks/identities and those items. The request/reply state machine,
mutation table, and item encryption (`IV || CTR || SHA-512`, random IV) are in `CRYPTO_RE_SALT.md` section 5. Open points: when edits rotate `sync_version_uuid`, the role of
`last_known_version`, the collision merge policy, and confirming the deletion tombstone before anything
destructive is sent.
## Etiquette
One sign-in is three requests. Don't loop sign-ins while testing; the service sits behind Cloudflare and
rate-limits abuse.