Git Product home page Git Product logo

tsdeclarations's Introduction

TeamSpeak Declarations

This repository contains all kind of data which is related to TeamSpeak.

This data is used for code generation in various projects, therefore all the data is machine readable.

The low level TeamSpeak protocol is described in ts3protocol.md.

License

Licensed under either of

at your option.

tsdeclarations's People

Contributors

berndschmecka avatar bluscream avatar braddevans avatar exp111 avatar flakebi avatar kd148 avatar rad3sh avatar rikku1338 avatar sossensystems avatar splamy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

tsdeclarations's Issues

Improvement suggestions for protocol paper

I finally managed to get my Python client to work with the new protocol (many thanks for your awesome work in researching and documenting it) and would like to make a few suggestions for improvements on the protocol paper to make things more clear for people who want to implement the protocol, too.

  • In section 3.2.2.4, it says "Teamspeak uses Curve25519 for all cryptographic operations.". This might be misleading, because TS is using AES for encryption and Prime256 + Ed25519 curves for signing/authenticating.
  • On multiple places, Curve25519 is mentioned with regards to key pairs and points, but I think we are actually using Ed25519, right?
  • It should be mentioned that the clientek packet already counts as Packet ID 1 rather than 0.
  • For deriving the key from the licenses, it should be explained that the Ed25519 private key is decoded like this:
    buffer := sha512(licenseBlock);
    // clamping
    buffer[0] &= ~0x07;
    buffer[31] &= 0x7F;
    buffer[31] |= 0x40;
    privateKey := buffer interpreted as a little-endian big int
  • It should be mentioned that the ECDSA signatures (proof parameter) must be calculated/verified using SHA256 and encoded in DER format (both are no default, at least in the library I am using).
  • Small typo in section 3.2.2.4: Should be SharedIV[10-64] instead of SharedIV[10-56]

General suggestions:

  • Explain how the values in the setconnectioninfo reply are calculated. I tried implementing the reply, but the server does not seem to accept my values (connection info window keeps "Loading").

How can I confirm the servers calculated public key?

I am currently implementing the last step of the crypto handshake and am kinda stuck on the clientek command. When I send it, it isn't being acknowledged. This means to me, that something went wrong on my side with calculating the servers public key (or the shared secret, but that part is rather straight forward from an implementations point of view).

I am not entierly sure, how to go about calulating the server's public key. This far I have the following go code:

func (l *License) serverPublicKey() ([]byte, error) {
    parent := rootKey
    for i := range l.Blocks { // iterate over the licenses blocks
        hash := sha512.Sum512(l.Blocks[i].Bytes()[1:])
        privateKey := edwards25519.NewScalar().SetBytesWithClamping(h[:32])
        publicKey := &edwards25519.Point{}.SetBytes(l.Blocks[i].PublicKey)
        next := &edwards25519.Point{}.ScalarMult(privateKey, publicKey)
        parent = next.Add(next, parent)
    }
    return parent.BytesMontgomery(), nil
}

I guess, you might not be an golang expert, but what I am basically doing here is:

  • Get the rootKey as an edwards25519 Point
  • iterate over the license blocks
  • calculate the (64 bytes long) sha512 hash of the block except the first byte
  • get the private key as a edwards25519 scalar using the first 32 bytes of the hash
  • get the public key as a edwards25519 point
  • calculate the point of publicKey * privateKey (point * scalar) as next
  • set the parent to next + parent
  • after the loop: return parent as bytes on the montgomery curve. I guess I have to do that, since edwards25519 != curve25519, but curve25519 is a montgomery curve so this should account for that (https://pkg.go.dev/filippo.io/edwards25519#Point.BytesMontgomery)

Am I doing something fundamentaly wrong here?

Btw: This is how I calculate the shared secret:

func sharedSecret(serverPublicKey []byte, alpha []byte, beta []byte) (sharedIV [64]byte, sharedMAC [8]byte, tempPublicKey []byte) {
    tempPrivateKey := edwards25519.NewScalar().SetBytesWithClamping(randomByteArray(length: 32))
    tempPublicKey := &edwards25519.Point{}.ScalarBaseMult(tempPrivateKey).Bytes()
    
    serverPub := &edwards25519.Point{}.SetBytes(serverPublicKey)
    sharedData := serverPub.ScalarMult(tempPrivateKey, serverPub)
    sharedIV = sha512.Sum512(sharedData.BytesMontgomery()[:32])

    // xor alpha
    for i := range alpha {
        sharedIV[i] ^= alpha[i]
    }
    // xor beta
    for i := range beta {
       sharedIV[10+i] ^= beta[i]
    }
    sharedMAC := sha1.Sum(sharedIV)[:8]
    return sharedIV, sharedMAC, tempPublicKey
}

Again: anything fundamentaly wrong here?

Thanks for any help you might be able to offer. I don't really know how I can debug that, hence my question: How can I check as a first step, if my calculated server public key is correct?

MfG

ANNOUNCEMENT

We will drop the 'channel' column from the Versions.csv as it is not really maintainable.
The master will be updated on 11.02.19

ot=1 parameter in `clientinitiv` missing from the protocol docs

Hello,
Thanks for the comprehensive document on the protocol. However while inspecting the official client with wireshark I noticed it sends an extra parameter on clientinitiv command (section 3.1) which is not listed in the docs.

ReSpeak also seems to send this parameter:
https://github.com/ReSpeak/tsclientlib/blob/5d0ee951bfbe3a5c0137a697bd53b35e0f2096fc/utils/tsproto-packets/src/packets.rs#L1081

Is there any explanation on what it does or can it be missing? should it be added to the protocol doc?

How do I calculate SharedIV and SharedMAC on the server side?

Hi, great team.

Problem description

I'm trying to implement a client and server in Golang and trying to interoperate with the client libraries tsclientlib you provide. I had one problem with the last step of the High-level encryption handshake on the server side, I read the relevant description in ts3protocol.md and I found that it is described from the client side perspective, not the server side.

I have passed the clientek part of the low-level handshake and high-level handshake and got the client_public_key, I want to know how the SharedIV and SharedMAC are calculated on the server side, is it calculated using the server's ed25519 private key (the one that corresponds to the public key of the last block Ephemeral Block in the license) and the public key sent by the client via the clientek command for X25519 scalar multiplication and then after performing the hash and some other operations?

Sorry I don't know much about cryptography related to elliptic curves, but it looks like it won't be equal to the SharedIV and SharedMAC calculated by the client with the server public key and the local temporary private key. And I guess the server and client must calculate the same SharedIV and SharedMAC in this one calculation session to achieve encrypted communication.

I'm stuck here and would appreciate your help or pointing out where I'm going wrong, I'll attach some of the relevant code below.

How do I calculate shared secret?

func sharedSecret(serverPrivateKey ed25519.PrivateKey, clientPublicKey ed25519.PublicKey, alpha, beta []byte) ([]byte, string, error) {
    sharedData, err := curve25519.X25519(serverPrivateKey, clientPublicKey)
    if err != nil {
        return nil, "", err
    }
    sharedIV := sha512.Sum512(sharedData[:32])

    // Xor alpha
    for i := range alpha {
        sharedIV[i] ^= alpha[i]
    }
    // Xor beta
    for i := range beta {
        sharedIV[10+i] ^= beta[i]
    }

    macHash := sha1.Sum(sharedIV[:])
    sharedMAC := macHash[:8]
    return sharedIV[:], string(sharedMAC), nil
}
  • The server private key is stored and exported when the license block is calculated, it looks like the client uses its corresponding public key as the public key named server_ek.
  • The client public key is the base64 decoded content of the ek value passed by the client from the clientek command, and I see that it is exactly the required 32 bytes in length.
  • BTW, after comparing I determined that the alpha and beta values used on the client and server are the same.

Thank you!

Issue with low level handshake

I have an issue with the low level handshake. I managed to build the first init packet and recieved the second init packet. The weird thing is, that the server has the compressed flag set and judging from the data, it is not compressed. However, the data contains the number (0x01) and then it follows with (0x00 0x00 0x02 \n) and then all zeros? I am using server version 3.13.3 running in docker although I get the same result with it running in podman and on bare linux

As you can imagine I cannot complete the handshake, since the server doesn't respond with a package when I try sending the third init package. I think something changed or at least works differently than you described in your document. Do you have any insight in what is going on here and possibly even how I should continue?

Omega key from initivexpand2

Hey, to put some context in place, I am writing teamspeak protocol in javascript (nodejs) with help of looking at some projects like splamys audiobot, ts3j or https://github.com/PankTrue/ts3client/tree/master/Ts3Client (I used this project to help me encrypt/decrypt packets with dummy keys) which is unfortunately outdated <3,1 so it does not support "initivexpand2".

I also took packet encryption/decryption functions from that ts3client and compiled them as an native addon as nodejs had some native support issues or I was simply dumb (more likely)

Now to the point, I fully implemented everything up to 3.2.2.1 Verify integrity and the issue lies with the Omega key and trying to import it to verify the integrity, but it always errors out no matter which library I use (crypto, node-forge, elliptic, p256 ...).

    handleInitivexpand2 = (keyValue) => {
        const omegaHEX = Buffer.from(keyValue.omega, "base64");
        const publicKey = crypto.createPublicKey(omegaHEX); //obviously I also tried various parameters and different arguments 
        ...
    };

which results in

Error: error:0909006C:PEM routines:get_name:no start line
    at Object.createPublicKey (node:internal/crypto/keys:607:12)
    at TeamspeakProtocol.handleInitivexpand2 (/home/ts3/ts3.js:204:34)
    at TeamspeakProtocol.handleCommand (/home/ts3/ts3.js:198:25)
    at Socket.onMessage (/home/ts3/ts3.js:146:30)
    at Socket.emit (node:events:513:28)
    at UDP.onMessage [as onmessage] (node:dgram:930:8) {
  library: 'PEM routines',
  function: 'get_name',
  reason: 'no start line',
  code: 'ERR_OSSL_PEM_NO_START_LINE'
}

(even though error mentions PEM, input can be anything, the code can detect der, pem..., my key simply doesnt seem to be valid, or has extra bytes)

I do not expect you to work in NodeJS or find the solution for me, but could you give me some hint as what exactly the omega is? Is it some ASN,1 Public Key in DER format? Or what exactly it is, I would really appreciate as much information as possible, maybe even "steps".

I even tried to write this verification code in C/C++ with help of google and chatgpt (yes I know, I needed all the help I could) using libtomcrypto, cryptopp or openssl but all of my attempts failed, which means I am missing some information.

Thanks!

BookToMessages.toml

Prototype for setter geneation

# As in M2B from/to properties can be automatically mapped when they have
# the same high-level name.

[[rule]]
# From the Book
from = "Channel"
# Into message
to = "ChannelEdit"
operation = "update"
# Can be often empty
# Can be inferred from required message parameters
ids = []
properties = [
	{ from="ChannelName", to="ChannelName" },
	# Function which reads a value form the book and splits it up
	# into multiple message parameters
	{ from="MaxClientChannelInheritedFactoryGenerator" function="Bla", tolist=["asd"] }
]

[[rule]]
# From the Book
from = "Client"
# Into message
to = "ClientEdit"
operation = "update"

Todo

  • update details on how split/command packets get flagged
  • update commands in proto.md to refer to the *.csv file
  • clarify ^ as pow
  • make a note on modpow/montgomery in 2.5
  • Add tsbook update rules (see below)

tsbook update rules example:

:// order, cid, invokerid, invokername, invokeruid, reasonid, cpid
:// cid, invokerid, invokername, invokeruid, channel_order, channel_name, channel_topic, channel_flag_default, channel_flag_password, channel_flag_permanent, channel_flag_semi_permanent, channel_codec, channel_codec_quality, channel_needed_talk_power, channel_icon_id, channel_maxclients, channel_maxfamilyclients, channel_codec_latency_factor, channel_codec_is_unencrypted, channel_delete_delay, channel_flag_maxclients_unlimited, channel_flag_maxfamilyclients_unlimited, channel_flag_maxfamilyclients_inherited, channel_name_phonetic, cpid
:// cid, invokerid, invokername, invokeruid
# sdfsdf sdf sdf sdf sdf
ServerInit -> Connection+ ???
ChannelMoved -> Connection.Server.Channels[cid]
	cpid -> ParentChannelId
ChannelCreated -> Connection.Server.Channels[cid]+
	channel_order -> Order
	channel_name -> Name
	function_name -> (DeleteDelay)
	...
ChannelDeleted -> Connection.Server.Channels[cid]-

A1 & A2 explanation

Hey guys,
first of all thank you for your amazing work on this project!

I'm currently trying to write a TS3Server implementation, but i'm stuck in the Init-Phase... After Sending Packet 3 of the Handshake, the client doesn't respond any more. I'm pretty sure is has something to do with me sending an empty (all zeroes) A1* byte-array...

Unfortunately, your protocol-document doesnt specify, what exactly should come from the server in this step... Could you tell me, what the server has to send as A1* and A2*?

*A1 and A2 are the names from the byte-arrays as you named them in the following document:
Link to explanation in ts3protocol.md

No 'clientinit'-respond

Hello dear Team,

I'm using TS3 Server v3.13.3 and 'Client-Version' 3.5.7.

So far, I passed the low-handshake and sent 'clientivinit' and got a response (acknowledged). 'clientinit' will not get acknowledged. I think I got a problem calculating the sharedIV and Mac, I imported the public keys from the licenses as Ed25519 Point and I imported the whole block without key-type (block-pub-key, license-block-type, valid-before/after and content) as int.from_bytes(clamp(sha512(block[1..])[..32]), endian=big) after that I use the pub-key and multiplied it with the block-int + parent (root key/resulting key before). I generated the sharedSecret of my private key and that point as Ed25519 pub-key. I tried everything but nothing works :( It would be great if anyone can help me.

Here my code python-code:

def compute_iv_mac(ls: List['License'], private: bytes, alpha: bytes, beta: bytes) -> Tuple[bytes, bytes]:
key = b'\xcd\r\xe2\xae\xd4cEP\x9a~<\xfd\x8fh\xb3\xdcuU\xb2\x9d\xcc\xecs\xcd\x18u\x0f\x998\x12@\x8a'

for l in ls:
	parent = Ed25519.decode_point(key)
	
	priv = int.from_bytes(clamp(bytes(sha512(l.block[1:]).digest()[:32])), 'big')

	key = Ed25519.encode_point(l.public_key * priv + parent)

temp_iv = sha512(PrivateKey.load(private).do_exchange(PublicKey(key))[:32]).digest()

iv  = xor_bytes(temp_iv[:10], alpha) + xor_bytes(temp_iv[10:], beta)
mac = sha1(iv).digest()[:8]

return iv, mac

TS5 Version Sign?

How do you get those Version Hashes? Can you please find one for "5.0.0-alpha216 [Build: 1556918526] on Windows"?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.