Highly-opinionated (ex-bullshit-free) MTPROTO proxy for Telegram. If you use v1.0 or upgrade broke you proxy, please read the chapter Version 2
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. package faketls
  2. import (
  3. "crypto/hmac"
  4. "crypto/sha256"
  5. "encoding/binary"
  6. "fmt"
  7. "time"
  8. "github.com/9seconds/mtg/v2/mtglib/internal/faketls/record"
  9. )
  10. type ClientHello struct {
  11. Time time.Time
  12. Digest [RandomLen]byte
  13. SessionID []byte
  14. }
  15. func ParseClientHello(secret, handshake []byte) (ClientHello, error) {
  16. hello := ClientHello{}
  17. if len(handshake) < ClientHelloMinLen {
  18. return hello, fmt.Errorf("lengh of handshake is too small: %d", len(handshake))
  19. }
  20. if handshake[0] != HandshakeTypeClient {
  21. return hello, fmt.Errorf("unknown handshake type %#x", handshake[0])
  22. }
  23. copy(hello.Digest[:], handshake[ClientHelloRandomOffset:])
  24. for i := ClientHelloRandomOffset; i < ClientHelloRandomOffset+RandomLen; i++ {
  25. handshake[i] = 0
  26. }
  27. rec := record.AcquireRecord()
  28. defer record.ReleaseRecord(rec)
  29. rec.Type = record.TypeHandshake
  30. rec.Version = record.Version10
  31. rec.Payload.Write(handshake)
  32. // mac is calculated for the whole record, not only
  33. // for the payload part
  34. mac := hmac.New(sha256.New, secret)
  35. rec.Dump(mac)
  36. computedDigest := mac.Sum(nil)
  37. for i := 0; i < RandomLen; i++ {
  38. computedDigest[i] ^= hello.Digest[i]
  39. }
  40. for i := 0; i < RandomLen-4; i++ {
  41. if computedDigest[i] != 0 {
  42. return hello, ErrBadDigest
  43. }
  44. }
  45. timestamp := int64(binary.LittleEndian.Uint32(computedDigest[RandomLen-4:]))
  46. hello.Time = time.Unix(timestamp, 0)
  47. hello.SessionID = make([]byte, handshake[ClientHelloSessionIDOffset])
  48. copy(hello.SessionID, handshake[ClientHelloSessionIDOffset+1:])
  49. return hello, nil
  50. }