encryption.go 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. package io
  2. import (
  3. "crypto/cipher"
  4. "io"
  5. "github.com/v2ray/v2ray-core/common/log"
  6. )
  7. // CryptionReader is a general purpose reader that applies a stream cipher on top of a regular reader.
  8. type CryptionReader struct {
  9. stream cipher.Stream
  10. reader io.Reader
  11. }
  12. // NewCryptionReader creates a new CryptionReader instance from given stream cipher and reader.
  13. func NewCryptionReader(stream cipher.Stream, reader io.Reader) *CryptionReader {
  14. return &CryptionReader{
  15. stream: stream,
  16. reader: reader,
  17. }
  18. }
  19. // Read reads blocks from underlying reader, and crypt it. The content of blocks is modified in place.
  20. func (reader CryptionReader) Read(blocks []byte) (int, error) {
  21. nBytes, err := reader.reader.Read(blocks)
  22. if nBytes > 0 {
  23. reader.stream.XORKeyStream(blocks[:nBytes], blocks[:nBytes])
  24. }
  25. if err != nil && err != io.EOF {
  26. log.Error("Error reading blocks: %v", err)
  27. }
  28. return nBytes, err
  29. }
  30. // Cryption writer is a general purpose of byte stream writer that applies a stream cipher on top of a regular writer.
  31. type CryptionWriter struct {
  32. stream cipher.Stream
  33. writer io.Writer
  34. }
  35. // NewCryptionWriter creates a new CryptionWriter from given stream cipher and writer.
  36. func NewCryptionWriter(stream cipher.Stream, writer io.Writer) *CryptionWriter {
  37. return &CryptionWriter{
  38. stream: stream,
  39. writer: writer,
  40. }
  41. }
  42. // Crypt crypts the content of blocks without writing them into the underlying writer.
  43. func (writer CryptionWriter) Crypt(blocks []byte) {
  44. writer.stream.XORKeyStream(blocks, blocks)
  45. }
  46. // Write crypts the content of blocks in place, and then writes the give blocks to underlying writer.
  47. func (writer CryptionWriter) Write(blocks []byte) (int, error) {
  48. writer.Crypt(blocks)
  49. return writer.writer.Write(blocks)
  50. }