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.8KB

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