Przeglądaj źródła

Add blockcipherrwc

tags/0.9
9seconds 7 lat temu
rodzic
commit
b74cc8d3ea
1 zmienionych plików z 84 dodań i 0 usunięć
  1. 84
    0
      wrappers/blockcipherrwc.go

+ 84
- 0
wrappers/blockcipherrwc.go Wyświetl plik

@@ -0,0 +1,84 @@
1
+package wrappers
2
+
3
+import (
4
+	"bytes"
5
+	"crypto/aes"
6
+	"crypto/cipher"
7
+	"io"
8
+
9
+	"github.com/juju/errors"
10
+)
11
+
12
+type BlockCipherReadWriteCloser struct {
13
+	buf *bytes.Buffer
14
+
15
+	conn      io.ReadWriteCloser
16
+	encryptor cipher.BlockMode
17
+	decryptor cipher.BlockMode
18
+}
19
+
20
+func (c *BlockCipherReadWriteCloser) Read(p []byte) (int, error) {
21
+	if c.buf.Len() > 0 {
22
+		return c.flush(p)
23
+	}
24
+
25
+	for c.buf.Len() == 0 || c.buf.Len()%aes.BlockSize != 0 {
26
+		n, err := c.conn.Read(p)
27
+		if err != nil {
28
+			return 0, errors.Annotate(err, "Cannot read from socket")
29
+		}
30
+		c.buf.Write(p[:n])
31
+	}
32
+
33
+	return c.flush(p)
34
+}
35
+
36
+func (c *BlockCipherReadWriteCloser) Write(p []byte) (int, error) {
37
+	if len(p)%aes.BlockSize > 0 {
38
+		return 0, errors.Errorf("Incorrect block size %d", len(p))
39
+	}
40
+
41
+	buf := getBuffer()
42
+	defer putBuffer(buf)
43
+	buf.Grow(len(p))
44
+	buf.Write(p)
45
+
46
+	encrypted := buf.Bytes()
47
+	c.encryptor.CryptBlocks(encrypted, p)
48
+
49
+	return c.conn.Write(encrypted)
50
+}
51
+
52
+func (c *BlockCipherReadWriteCloser) Close() error {
53
+	defer putBuffer(c.buf)
54
+	return c.conn.Close()
55
+}
56
+
57
+func (c *BlockCipherReadWriteCloser) flush(p []byte) (int, error) {
58
+	sizeToRead := len(p)
59
+	if c.buf.Len() < sizeToRead {
60
+		sizeToRead = c.buf.Len()
61
+	}
62
+	sizeToRead = aes.BlockSize * (sizeToRead / aes.BlockSize)
63
+
64
+	c.decryptor.CryptBlocks(p, c.buf.Bytes()[:sizeToRead])
65
+	if sizeToRead == c.buf.Len() {
66
+		c.buf.Reset()
67
+	} else {
68
+		leftover := c.buf.Bytes()[sizeToRead:]
69
+		putBuffer(c.buf)
70
+		c.buf = getBuffer()
71
+		c.buf.Write(leftover)
72
+	}
73
+
74
+	return sizeToRead, nil
75
+}
76
+
77
+func NewBlockCipherRWC(conn io.ReadWriteCloser, encryptor, decryptor cipher.BlockMode) io.ReadWriteCloser {
78
+	return &BlockCipherReadWriteCloser{
79
+		buf:       getBuffer(),
80
+		conn:      conn,
81
+		encryptor: encryptor,
82
+		decryptor: decryptor,
83
+	}
84
+}

Ładowanie…
Anuluj
Zapisz