xor.go 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package encryption
  2. import (
  3. "crypto/aes"
  4. "crypto/cipher"
  5. "net"
  6. "lukechampine.com/blake3"
  7. )
  8. func NewCTR(key, iv []byte) cipher.Stream {
  9. k := make([]byte, 32)
  10. blake3.DeriveKey(k, "VLESS", key) // avoids using key directly
  11. block, _ := aes.NewCipher(k)
  12. return cipher.NewCTR(block, iv)
  13. //chacha20.NewUnauthenticatedCipher()
  14. }
  15. type XorConn struct {
  16. net.Conn
  17. CTR cipher.Stream
  18. PeerCTR cipher.Stream
  19. OutSkip int
  20. OutHeader []byte
  21. InSkip int
  22. InHeader []byte
  23. }
  24. func NewXorConn(conn net.Conn, ctr, peerCTR cipher.Stream, outSkip, inSkip int) *XorConn {
  25. return &XorConn{
  26. Conn: conn,
  27. CTR: ctr,
  28. PeerCTR: peerCTR,
  29. OutSkip: outSkip,
  30. OutHeader: make([]byte, 0, 5), // important
  31. InSkip: inSkip,
  32. InHeader: make([]byte, 0, 5), // important
  33. }
  34. }
  35. func (c *XorConn) Write(b []byte) (int, error) {
  36. if len(b) == 0 {
  37. return 0, nil
  38. }
  39. for p := b; ; {
  40. if len(p) <= c.OutSkip {
  41. c.OutSkip -= len(p)
  42. break
  43. }
  44. p = p[c.OutSkip:]
  45. c.OutSkip = 0
  46. need := 5 - len(c.OutHeader)
  47. if len(p) < need {
  48. c.OutHeader = append(c.OutHeader, p...)
  49. c.CTR.XORKeyStream(p, p)
  50. break
  51. }
  52. c.OutSkip, _ = DecodeHeader(append(c.OutHeader, p[:need]...))
  53. c.OutHeader = c.OutHeader[:0]
  54. c.CTR.XORKeyStream(p[:need], p[:need])
  55. p = p[need:]
  56. }
  57. if _, err := c.Conn.Write(b); err != nil {
  58. return 0, err
  59. }
  60. return len(b), nil
  61. }
  62. func (c *XorConn) Read(b []byte) (int, error) {
  63. if len(b) == 0 {
  64. return 0, nil
  65. }
  66. n, err := c.Conn.Read(b)
  67. for p := b[:n]; ; {
  68. if len(p) <= c.InSkip {
  69. c.InSkip -= len(p)
  70. break
  71. }
  72. p = p[c.InSkip:]
  73. c.InSkip = 0
  74. need := 5 - len(c.InHeader)
  75. if len(p) < need {
  76. c.PeerCTR.XORKeyStream(p, p)
  77. c.InHeader = append(c.InHeader, p...)
  78. break
  79. }
  80. c.PeerCTR.XORKeyStream(p[:need], p[:need])
  81. c.InSkip, _ = DecodeHeader(append(c.InHeader, p[:need]...))
  82. c.InHeader = c.InHeader[:0]
  83. p = p[need:]
  84. }
  85. return n, err
  86. }