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.

blockcipher.go 3.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. package wrappers
  2. import (
  3. "bytes"
  4. "crypto/aes"
  5. "crypto/cipher"
  6. "errors"
  7. "fmt"
  8. "net"
  9. "time"
  10. "go.uber.org/zap"
  11. "github.com/9seconds/mtg/conntypes"
  12. )
  13. const blockCipherReadCurrentDataBufferSize = 1024 + 1 // +1 because telegram operates with blocks mod 4
  14. type wrapperBlockCipher struct {
  15. buf bytes.Buffer
  16. parent conntypes.StreamReadWriteCloser
  17. encryptor cipher.BlockMode
  18. decryptor cipher.BlockMode
  19. }
  20. func (w *wrapperBlockCipher) Write(p []byte) (int, error) {
  21. encrypted, err := w.encrypt(p)
  22. if err != nil {
  23. return 0, err
  24. }
  25. return w.parent.Write(encrypted)
  26. }
  27. func (w *wrapperBlockCipher) WriteTimeout(p []byte, timeout time.Duration) (int, error) {
  28. encrypted, err := w.encrypt(p)
  29. if err != nil {
  30. return 0, err
  31. }
  32. return w.parent.WriteTimeout(encrypted, timeout)
  33. }
  34. func (w *wrapperBlockCipher) Read(p []byte) (int, error) {
  35. return w.read(p, readAll)
  36. }
  37. func (w *wrapperBlockCipher) ReadTimeout(p []byte, timeout time.Duration) (int, error) {
  38. return w.read(p, readAllTimeout(timeout))
  39. }
  40. func (w *wrapperBlockCipher) read(p []byte,
  41. reader func(conntypes.StreamReadWriteCloser) ([]byte, error)) (int, error) {
  42. if w.buf.Len() > 0 {
  43. return w.flush(p)
  44. }
  45. var buf []byte
  46. for len(buf) == 0 || len(buf)%aes.BlockSize != 0 {
  47. rv, err := reader(w.parent)
  48. if err != nil {
  49. return 0, fmt.Errorf("cannot read from socket: %w", err)
  50. }
  51. buf = append(buf, rv...)
  52. }
  53. w.decryptor.CryptBlocks(buf, buf)
  54. w.buf.Write(buf)
  55. return w.flush(p)
  56. }
  57. func (w *wrapperBlockCipher) flush(p []byte) (int, error) {
  58. if w.buf.Len() > len(p) {
  59. return w.buf.Read(p)
  60. }
  61. sizeToReturn := w.buf.Len()
  62. copy(p, w.buf.Bytes())
  63. w.buf.Reset()
  64. return sizeToReturn, nil
  65. }
  66. func (w *wrapperBlockCipher) encrypt(p []byte) ([]byte, error) {
  67. if len(p)%aes.BlockSize > 0 {
  68. return nil, fmt.Errorf("incorrect block size %d", len(p))
  69. }
  70. encrypted := make([]byte, len(p))
  71. w.encryptor.CryptBlocks(encrypted, p)
  72. return encrypted, nil
  73. }
  74. func readAll(src conntypes.StreamReadWriteCloser) (rv []byte, err error) {
  75. buf := make([]byte, blockCipherReadCurrentDataBufferSize)
  76. n := blockCipherReadCurrentDataBufferSize
  77. for n == len(buf) {
  78. n, err = src.Read(buf)
  79. if err != nil {
  80. return nil, err
  81. }
  82. rv = append(rv, buf[:n]...)
  83. }
  84. return rv, nil
  85. }
  86. func readAllTimeout(timeout time.Duration) func(conntypes.StreamReadWriteCloser) ([]byte, error) {
  87. return func(src conntypes.StreamReadWriteCloser) (rv []byte, err error) {
  88. tmo := timeout
  89. buf := make([]byte, blockCipherReadCurrentDataBufferSize)
  90. n := blockCipherReadCurrentDataBufferSize
  91. for n == len(buf) {
  92. if tmo <= 0 {
  93. return nil, errors.New("timeout")
  94. }
  95. startTime := time.Now()
  96. n, err = src.ReadTimeout(buf, tmo)
  97. if err != nil {
  98. return nil, err
  99. }
  100. rv = append(rv, buf[:n]...)
  101. tmo -= time.Since(startTime)
  102. }
  103. return rv, nil
  104. }
  105. }
  106. func (w *wrapperBlockCipher) Close() error {
  107. return w.parent.Close()
  108. }
  109. func (w *wrapperBlockCipher) Conn() net.Conn {
  110. return w.parent.Conn()
  111. }
  112. func (w *wrapperBlockCipher) Logger() *zap.SugaredLogger {
  113. return w.parent.Logger().Named("block-cipher")
  114. }
  115. func (w *wrapperBlockCipher) LocalAddr() *net.TCPAddr {
  116. return w.parent.LocalAddr()
  117. }
  118. func (w *wrapperBlockCipher) RemoteAddr() *net.TCPAddr {
  119. return w.parent.RemoteAddr()
  120. }
  121. func newBlockCipher(parent conntypes.StreamReadWriteCloser,
  122. encryptor, decryptor cipher.BlockMode) conntypes.StreamReadWriteCloser {
  123. return &wrapperBlockCipher{
  124. parent: parent,
  125. encryptor: encryptor,
  126. decryptor: decryptor,
  127. }
  128. }