github.com/simonmittag/ws@v1.1.0-rc.5.0.20210419231947-82b846128245/wsutil/cipher.go (about) 1 package wsutil 2 3 import ( 4 "io" 5 6 "github.com/gobwas/pool/pbytes" 7 "github.com/simonmittag/ws" 8 ) 9 10 // CipherReader implements io.Reader that applies xor-cipher to the bytes read 11 // from source. 12 // It could help to unmask WebSocket frame payload on the fly. 13 type CipherReader struct { 14 r io.Reader 15 mask [4]byte 16 pos int 17 } 18 19 // NewCipherReader creates xor-cipher reader from r with given mask. 20 func NewCipherReader(r io.Reader, mask [4]byte) *CipherReader { 21 return &CipherReader{r, mask, 0} 22 } 23 24 // Reset resets CipherReader to read from r with given mask. 25 func (c *CipherReader) Reset(r io.Reader, mask [4]byte) { 26 c.r = r 27 c.mask = mask 28 c.pos = 0 29 } 30 31 // Read implements io.Reader interface. It applies mask given during 32 // initialization to every read byte. 33 func (c *CipherReader) Read(p []byte) (n int, err error) { 34 n, err = c.r.Read(p) 35 ws.Cipher(p[:n], c.mask, c.pos) 36 c.pos += n 37 return 38 } 39 40 // CipherWriter implements io.Writer that applies xor-cipher to the bytes 41 // written to the destination writer. It does not modify the original bytes. 42 type CipherWriter struct { 43 w io.Writer 44 mask [4]byte 45 pos int 46 } 47 48 // NewCipherWriter creates xor-cipher writer to w with given mask. 49 func NewCipherWriter(w io.Writer, mask [4]byte) *CipherWriter { 50 return &CipherWriter{w, mask, 0} 51 } 52 53 // Reset reset CipherWriter to write to w with given mask. 54 func (c *CipherWriter) Reset(w io.Writer, mask [4]byte) { 55 c.w = w 56 c.mask = mask 57 c.pos = 0 58 } 59 60 // Write implements io.Writer interface. It applies masking during 61 // initialization to every sent byte. It does not modify original slice. 62 func (c *CipherWriter) Write(p []byte) (n int, err error) { 63 cp := pbytes.GetLen(len(p)) 64 defer pbytes.Put(cp) 65 66 copy(cp, p) 67 ws.Cipher(cp, c.mask, c.pos) 68 n, err = c.w.Write(cp) 69 c.pos += n 70 71 return 72 }