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
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

mtproto_cipher.go 2.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. package wrappers
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "crypto/md5"
  7. "crypto/sha1"
  8. "encoding/binary"
  9. "net"
  10. "github.com/9seconds/mtg/mtproto/rpc"
  11. "github.com/9seconds/mtg/utils"
  12. )
  13. type mtprotoCipherPurpose uint8
  14. const (
  15. mtprotoCipherPurposeClient mtprotoCipherPurpose = iota
  16. mtprotoCipherPurposeServer
  17. )
  18. var mtprotoEmptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
  19. func NewMiddleProxyCipher(parent StreamReadWriteCloser,
  20. req *rpc.NonceRequest,
  21. resp *rpc.NonceResponse,
  22. secret []byte) StreamReadWriteCloser {
  23. localAddr := parent.LocalAddr()
  24. remoteAddr := parent.RemoteAddr()
  25. encKey, encIV := mtprotoDeriveKeys(mtprotoCipherPurposeClient,
  26. req,
  27. resp,
  28. localAddr,
  29. remoteAddr,
  30. secret)
  31. decKey, decIV := mtprotoDeriveKeys(mtprotoCipherPurposeServer,
  32. req,
  33. resp,
  34. localAddr,
  35. remoteAddr,
  36. secret)
  37. enc, _ := mtprotoMakeEncrypterDecrypter(encKey, encIV)
  38. _, dec := mtprotoMakeEncrypterDecrypter(decKey, decIV)
  39. return newBlockCipher(parent, enc, dec)
  40. }
  41. func mtprotoDeriveKeys(purpose mtprotoCipherPurpose,
  42. req *rpc.NonceRequest,
  43. resp *rpc.NonceResponse,
  44. client, remote *net.TCPAddr,
  45. secret []byte) ([]byte, []byte) {
  46. message := bytes.Buffer{}
  47. message.Write(resp.Nonce) // nolint: gosec
  48. message.Write(req.Nonce) // nolint: gosec
  49. message.Write(req.CryptoTS) // nolint: gosec
  50. clientIPv4 := mtprotoEmptyIP[:]
  51. serverIPv4 := mtprotoEmptyIP[:]
  52. if client.IP.To4() != nil {
  53. clientIPv4 = utils.ReverseBytes(client.IP.To4())
  54. serverIPv4 = utils.ReverseBytes(remote.IP.To4())
  55. }
  56. message.Write(serverIPv4) // nolint: gosec
  57. var port [2]byte
  58. binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
  59. message.Write(port[:]) // nolint: gosec
  60. switch purpose {
  61. case mtprotoCipherPurposeClient:
  62. message.WriteString("CLIENT") // nolint: gosec
  63. case mtprotoCipherPurposeServer:
  64. message.WriteString("SERVER") // nolint: gosec
  65. default:
  66. panic("Unexpected cipher purpose")
  67. }
  68. message.Write(clientIPv4) // nolint: gosec
  69. binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
  70. message.Write(port[:]) // nolint: gosec
  71. message.Write(secret) // nolint: gosec
  72. message.Write(resp.Nonce) // nolint: gosec
  73. if client.IP.To4() == nil {
  74. message.Write(client.IP.To16()) // nolint: gosec
  75. message.Write(remote.IP.To16()) // nolint: gosec
  76. }
  77. message.Write(req.Nonce) // nolint: gosec
  78. data := message.Bytes()
  79. md5sum := md5.Sum(data[1:]) // nolint: gas
  80. sha1sum := sha1.Sum(data) // nolint: gosec
  81. key := append(md5sum[:12], sha1sum[:]...)
  82. iv := md5.Sum(data[2:]) // nolint: gas
  83. return key, iv[:]
  84. }
  85. func mtprotoMakeEncrypterDecrypter(key, iv []byte) (cipher.BlockMode, cipher.BlockMode) {
  86. block, err := aes.NewCipher(key)
  87. if err != nil {
  88. panic(err)
  89. }
  90. return cipher.NewCBCEncrypter(block, iv), cipher.NewCBCDecrypter(block, iv)
  91. }