-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcipher_writer.go
59 lines (54 loc) · 1.66 KB
/
cipher_writer.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package okapi
import (
"io"
)
// CipherWriter encrypts written bytes then writes the encrypted bytes into the underlying Writer.
// CipherWriter MUST be closed before it's discarded.
type CipherWriter struct {
output io.Writer
buffer []byte
cipher Cipher
}
// NewCipherWriter creates CipherWriter wrapped around the provided Writer.
// The associated cipher is created from the provided CipherSpec, key and iv.
// The optional buffer is used internally. If buffer is not provided,
// it will be created with DefaultBufferSize.
func NewCipherWriter(out io.Writer, cs CipherSpec, key, iv, buffer []byte) *CipherWriter {
if buffer == nil {
buffer = make([]byte, DefaultBufferSize)
}
return &CipherWriter{output: out, cipher: cs.New(key, iv, true), buffer: buffer}
}
// Write encrypts bytes from the provided slice and writes the encrypted bytes into the underlying writer.
func (w *CipherWriter) Write(in []byte) (int, error) {
var (
total = 0
ins = 0
outs = 0
)
for total < len(in) {
ins, outs = w.cipher.Update(in[total:], w.buffer)
total += ins
_, err := w.output.Write(w.buffer[:outs])
if err != nil {
return total, err
}
}
return total, nil
}
// Close finishes encryption of any pending input and writes it into the underlying Writer.
// Then it releases associated resources, e.g. the cipher.
// If the underlying Writer is a Closer, it will close it as well.
func (w *CipherWriter) Close() error {
defer w.cipher.Close()
encrypted := w.cipher.Finish(w.buffer)
if encrypted != 0 {
if _, err := w.output.Write(w.buffer[:encrypted]); err != nil {
return err
}
}
if closer, ok := w.output.(io.Closer); ok {
return closer.Close()
}
return nil
}