forked from dgryski/dkeyczar
-
Notifications
You must be signed in to change notification settings - Fork 0
/
controllers.go
201 lines (179 loc) · 4.8 KB
/
controllers.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
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
/*
Package dkeyczar is a simplified wrapper around Go's native cryptography libraries.
It is modeled after and compatible with Google's Keyczar library (http://keyczar.org)
Sample usage is:
reader := NewFileReader("/path/to/keys")
crypter := NewCrypter(reader)
ciphertext := crypter.Encrypt(plaintext)
Decryption, Signing and Verification use the same minimal API.
Encrypted data and signatures are encoded with web-safe base64.
*/
package dkeyczar
import (
"bytes"
"compress/gzip"
"compress/zlib"
"encoding/base64"
"io"
)
type Encoding int
const (
BASE64W Encoding = iota // Encode the output with web-safe base64 [default]
NO_ENCODING // Do not encode the output
)
type Compression int
const (
NO_COMPRESSION Compression = iota // Do not compress the plaintext before encrypting [default]
GZIP // Use gzip compression
ZLIB // Use zlib compression
)
type CompressionController interface {
// Set the current compression level
SetCompression(compression Compression)
// Return the current compression level
Compression() Compression
}
type EncodingController interface {
// Set the current output encoding
SetEncoding(encoding Encoding)
// Return the current output encoding
Encoding() Encoding
}
type encodingController struct {
encoding Encoding
}
// Encoding returns the current output encoding for the keyczar object
func (ec encodingController) Encoding() Encoding {
return ec.encoding
}
// SetEncoding sets the current output encoding for the keyczar object
func (ec *encodingController) SetEncoding(encoding Encoding) {
ec.encoding = encoding
}
// return 'data' encoded based on the value of the 'encoding' field
func (ec encodingController) encode(data []byte) string {
switch ec.encoding {
case NO_ENCODING:
return string(data)
case BASE64W:
return encodeWeb64String(data)
}
panic("not reached")
}
func (ec encodingController) encodeWriter(data io.Writer) io.WriteCloser {
switch ec.encoding {
case NO_ENCODING:
return newNopWriteCloser(data)
case BASE64W:
return base64.NewEncoder(base64.RawURLEncoding, data)
}
panic("not reached")
}
// return 'data' decoded based on the value of the 'encoding' field
func (ec encodingController) decode(data string) ([]byte, error) {
switch ec.encoding {
case NO_ENCODING:
return []byte(data), nil
case BASE64W:
return decodeWeb64String(data)
}
panic("not reached")
}
func (ec encodingController) decodeReader(data io.Reader) io.Reader {
switch ec.encoding {
case NO_ENCODING:
return data
case BASE64W:
return base64.NewDecoder(base64.RawURLEncoding, data)
}
panic("not reached")
}
type compressionController struct {
compression Compression
}
// Compression returns the current compression type for keyczar object
func (cc compressionController) Compression() Compression {
return cc.compression
}
// SetCompression sets the current compression type for the keyczar object
func (cc *compressionController) SetCompression(compression Compression) {
cc.compression = compression
}
// return 'data' compressed based on the value of the 'compression' field
func (cc compressionController) compress(data []byte) []byte {
switch cc.compression {
case NO_COMPRESSION:
return data
case GZIP:
var b bytes.Buffer
w := gzip.NewWriter(&b)
w.Write(data)
w.Close()
return b.Bytes()
case ZLIB:
var b bytes.Buffer
w := zlib.NewWriter(&b)
w.Write(data)
w.Close()
return b.Bytes()
}
panic("not reached")
}
func (cc compressionController) compressWriter(data io.Writer) io.WriteCloser {
switch cc.compression {
case GZIP:
datac, _ := gzip.NewWriterLevel(data, gzip.BestCompression)
return datac
case ZLIB:
datac, _ := zlib.NewWriterLevel(data, zlib.BestCompression)
return datac
}
return newNopWriteCloser(data)
}
// return 'data' decompressed based on the value of the 'compression' field
func (cc compressionController) decompress(data []byte) ([]byte, error) {
switch cc.compression {
case NO_COMPRESSION:
return data, nil
case GZIP:
b := bytes.NewBuffer(data)
r, err := gzip.NewReader(b)
if err != nil {
return nil, err
}
var br bytes.Buffer
io.Copy(&br, r)
r.Close()
return (&br).Bytes(), nil
case ZLIB:
b := bytes.NewBuffer(data)
r, err := zlib.NewReader(b)
if err != nil {
return nil, err
}
var br bytes.Buffer
io.Copy(&br, r)
r.Close()
return (&br).Bytes(), nil
}
panic("not reached")
}
func (cc compressionController) decompressReader(data io.ReadCloser) (io.ReadCloser, error) {
switch cc.compression {
case NO_COMPRESSION:
return data, nil
case GZIP:
r, err := gzip.NewReader(data)
if err != nil {
return nil, err
}
return linkReaderCloser(r, data), err
case ZLIB:
r, err := zlib.NewReader(data)
if err != nil {
return nil, err
}
return nestReaderCloser(r, data), nil
}
panic("unknown compressor")
}