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.

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package mtglib
  2. import (
  3. "crypto/rand"
  4. "encoding/base64"
  5. "encoding/hex"
  6. "fmt"
  7. "strings"
  8. )
  9. const SecretKeyLength = 16
  10. type Secret struct {
  11. Key []byte
  12. Host string
  13. }
  14. func (s *Secret) MarshalText() ([]byte, error) {
  15. if s == nil {
  16. return nil, nil
  17. }
  18. return []byte(s.String()), nil
  19. }
  20. func (s *Secret) UnmarshalText(data []byte) error {
  21. text := string(data)
  22. if text == "" {
  23. return ErrSecretEmpty
  24. }
  25. var (
  26. decoded []byte
  27. err error
  28. )
  29. if strings.HasPrefix(text, "ee") {
  30. decoded, err = hex.DecodeString(strings.TrimPrefix(text, "ee"))
  31. }
  32. if err != nil || len(decoded) <= SecretKeyLength {
  33. decoded, err = base64.RawURLEncoding.DecodeString(text)
  34. }
  35. if err != nil {
  36. return fmt.Errorf("incorrect secret format: %w", err)
  37. }
  38. if len(decoded) <= SecretKeyLength {
  39. return fmt.Errorf("secret has incorrect length %d", len(text))
  40. }
  41. s.Key = decoded[:SecretKeyLength]
  42. s.Host = string(decoded[SecretKeyLength:])
  43. return nil
  44. }
  45. func (s Secret) Base64() string {
  46. data := append([]byte{238}, s.Key...) // 238 = hex ee
  47. data = append(data, s.Host...)
  48. return base64.RawURLEncoding.EncodeToString(data)
  49. }
  50. func (s Secret) String() string {
  51. return s.Base64()
  52. }
  53. func (s Secret) EE() string {
  54. return "ee" + hex.EncodeToString(append(s.Key, s.Host...))
  55. }
  56. func GenerateSecret(hostname string) Secret {
  57. s := Secret{
  58. Key: make([]byte, SecretKeyLength),
  59. Host: hostname,
  60. }
  61. if _, err := rand.Read(s.Key); err != nil {
  62. panic(err)
  63. }
  64. return s
  65. }