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
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

crypt.go 2.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  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/wrappers"
  12. )
  13. type CipherPurpose uint8
  14. const (
  15. CipherPurposeClient CipherPurpose = iota
  16. CipherPurposeServer
  17. )
  18. var emptyIP = [4]byte{0x00, 0x00, 0x00, 0x00}
  19. func NewMiddleProxyCipherRWC(conn wrappers.ReadWriteCloserWithAddr, req *rpc.RPCNonceRequest,
  20. resp *rpc.RPCNonceResponse, client *net.TCPAddr, secret []byte) wrappers.ReadWriteCloserWithAddr {
  21. remote := conn.Addr()
  22. encryptor, _ := newCBCCipher(CipherPurposeClient, req, resp, client, remote, secret)
  23. _, decryptor := newCBCCipher(CipherPurposeServer, req, resp, client, remote, secret)
  24. return wrappers.NewBlockCipherRWC(conn, encryptor, decryptor)
  25. }
  26. func newCBCCipher(purpose CipherPurpose, req *rpc.RPCNonceRequest, resp *rpc.RPCNonceResponse,
  27. client *net.TCPAddr, remote *net.TCPAddr, secret []byte) (cipher.BlockMode, cipher.BlockMode) {
  28. message := bytes.Buffer{}
  29. message.Write(resp.Nonce[:])
  30. message.Write(req.Nonce[:])
  31. message.Write(req.CryptoTS[:])
  32. clientIPv4 := emptyIP[:]
  33. serverIPv4 := emptyIP[:]
  34. if client.IP.To4() != nil {
  35. clientIPv4 = reverseBytes(client.IP.To4())
  36. serverIPv4 = reverseBytes(remote.IP.To4())
  37. }
  38. message.Write(serverIPv4)
  39. var port [2]byte
  40. binary.LittleEndian.PutUint16(port[:], uint16(client.Port))
  41. message.Write(port[:])
  42. switch purpose {
  43. case CipherPurposeClient:
  44. message.WriteString("CLIENT")
  45. case CipherPurposeServer:
  46. message.WriteString("SERVER")
  47. default:
  48. panic("Unexpected cipher purpose")
  49. }
  50. message.Write(clientIPv4)
  51. binary.LittleEndian.PutUint16(port[:], uint16(remote.Port))
  52. message.Write(port[:])
  53. message.Write(secret)
  54. message.Write(resp.Nonce[:])
  55. if client.IP.To4() == nil {
  56. message.Write(client.IP.To16())
  57. message.Write(remote.IP.To16())
  58. }
  59. message.Write(req.Nonce[:])
  60. return makeCipher(message.Bytes())
  61. }
  62. func makeCipher(message []byte) (cipher.BlockMode, cipher.BlockMode) {
  63. md5sum := md5.Sum(message[1:])
  64. sha1sum := sha1.Sum(message)
  65. key := append(md5sum[12:], sha1sum[:]...)
  66. iv := md5.Sum(message[2:])
  67. block, err := aes.NewCipher(key)
  68. if err != nil {
  69. panic("Cannot create cipher from the given key")
  70. }
  71. return cipher.NewCBCEncrypter(block, iv[:]), cipher.NewCBCDecrypter(block, iv[:])
  72. }
  73. func reverseBytes(data []byte) []byte {
  74. rv := make([]byte, len(data))
  75. for k, v := range data {
  76. rv[len(data)-1-k] = v
  77. }
  78. return rv
  79. }