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.

mtproto_cipher.go 2.5KB

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