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.

blockcipherrwc.go 1.6KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. package wrappers
  2. import (
  3. "bytes"
  4. "crypto/cipher"
  5. "io"
  6. "github.com/juju/errors"
  7. )
  8. type BlockCipherReadWriteCloser struct {
  9. encryptor cipher.BlockMode
  10. decryptor cipher.BlockMode
  11. conn io.ReadWriteCloser
  12. buf *bytes.Buffer
  13. }
  14. func (c *BlockCipherReadWriteCloser) Read(p []byte) (n int, err error) {
  15. blockSize := c.decryptor.BlockSize()
  16. if len(p) < blockSize {
  17. return 0, errors.New("Cannot read less than blocksize")
  18. }
  19. n, err = c.conn.Read(p)
  20. c.buf.Write(p[:n])
  21. wantToRead := c.getFullBlocks(len(p), blockSize)
  22. haveBlocks := c.getFullBlocks(c.buf.Len(), blockSize)
  23. if haveBlocks < wantToRead {
  24. wantToRead = haveBlocks
  25. }
  26. wantToRead *= blockSize
  27. data := c.buf.Bytes()
  28. c.decryptor.CryptBlocks(p, data[:wantToRead])
  29. c.buf = bytes.NewBuffer(data[wantToRead:])
  30. return wantToRead, err
  31. }
  32. func (c *BlockCipherReadWriteCloser) Write(p []byte) (n int, err error) {
  33. blockSize := c.encryptor.BlockSize()
  34. if len(p)%blockSize != 0 {
  35. return 0, errors.New("Write size should be compatible with block size")
  36. }
  37. buf := make([]byte, len(p))
  38. c.encryptor.CryptBlocks(buf, p)
  39. return c.conn.Write(buf)
  40. }
  41. func (c *BlockCipherReadWriteCloser) Close() error {
  42. return c.conn.Close()
  43. }
  44. func (c *BlockCipherReadWriteCloser) getFullBlocks(number, blockSize int) int {
  45. blocks := number / blockSize
  46. if blocks > 0 && number%blockSize != 0 {
  47. blocks--
  48. }
  49. return blocks
  50. }
  51. func NewBlockCipherRWC(conn io.ReadWriteCloser, encryptor, decryptor cipher.BlockMode) io.ReadWriteCloser {
  52. return &BlockCipherReadWriteCloser{
  53. conn: conn,
  54. encryptor: encryptor,
  55. decryptor: decryptor,
  56. }
  57. }