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>
3.2 KiB
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'sAccount_Data(which stores email, the login token in itspasswordfield, and the account key asencryption_password), it keepsMyTeamSpeak.Credentials— email, login token, account key — in the private profile filemyteamspeak.properties; never the password.signInderives them, reads the account and only then saves them;fetchreads the account again with the saved ones;signOutdeletes the file. When the server rejects saved credentials (ERROR_LOGIN_FAILED, e.g. the password was changed elsewhere)fetchsigns out.MyTeamSpeak.download(Credentials)— signs in (authentication/login), unwraps the item key, pulls BOOKMARK, IDENTITY and ITEM_FOLDER with onesynchronization/requestServerItemsagainst 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.keyunwrap (AES-256-GCM), item frame decryption (little-endian AES-CTR + SHA-512 trailer). SeeCRYPTO_RE_SALT.md.MyTsTransport— theapplication/ts3cloudframing over HTTP/1.1; an interface so tests replay a server.- Decrypted items are plain
Item_Data, decoded byteamspeak/SyncItemDecoder.TeamSpeakImportergainsimportSelected(all, chosen)(chosen bookmarks bring the identities they use) andisPresent(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.