-
Notifications
You must be signed in to change notification settings - Fork 0
/
Crypt.go
185 lines (152 loc) · 3.19 KB
/
Crypt.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
package libdatamanager
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"errors"
"io"
"os"
"strings"
)
// EncryptionCiphers supported encryption chipers
var EncryptionCiphers = []string{
"aes",
}
// ChiperToInt cipter to int
func ChiperToInt(c string) int32 {
c = strings.ToLower(c)
for i, ec := range EncryptionCiphers {
if c == strings.ToLower(ec) {
return int32(i) + 1
}
}
return 0
}
// EncryptionIValid return true if encryption i is valid
func EncryptionIValid(i int32) bool {
if i-1 < 0 || i-1 >= int32(len(EncryptionCiphers)) {
return false
}
return true
}
// ChiperToString cipter to int
func ChiperToString(i int32) string {
if !EncryptionIValid(i) {
return ""
}
return EncryptionCiphers[i-1]
}
// IsValidCipher return true if given cipher is valid
func IsValidCipher(c string) bool {
c = strings.ToLower(c)
for _, ec := range EncryptionCiphers {
if strings.ToLower(ec) == c {
return true
}
}
return false
}
// EncryptAES encrypts input stream and writes it to out
func EncryptAES(in io.Reader, out io.Writer, keyAes, buff []byte, cancel chan bool) (err error) {
iv := make([]byte, 16)
// Create random iv
_, err = rand.Read(iv)
if err != nil {
return err
}
aes, err := aes.NewCipher(keyAes)
if err != nil {
return err
}
ctr := cipher.NewCTR(aes, iv)
// First 16 bytes of ciphertext will
// be the iv, so write it!
out.Write(iv)
// Encrypt file
for {
// Stop on cancel
select {
case <-cancel:
return ErrCancelled
default:
}
n, err := in.Read(buff)
if err != nil && err != io.EOF {
return err
}
if n != 0 {
outBuf := make([]byte, n)
ctr.XORKeyStream(outBuf, buff[:n])
out.Write(outBuf)
}
if err == io.EOF {
break
}
}
return nil
}
// DecryptAES decrypt stuff
func DecryptAES(in io.Reader, out, hashwriter io.Writer, keyAes, buff []byte, cancelChan chan bool) (err error) {
// Iv is always 16 bytes
iv := make([]byte, 16)
aes, err := aes.NewCipher(keyAes)
if err != nil {
return err
}
// Read first 16 bytes to iv
n, err := in.Read(iv)
if err != nil {
return err
}
// If not 16 bytes were written, there
// is a big problem
if n != 16 {
return errors.New("reading aes iv")
}
// Write iv to hasher cause the servers
// hash is built on it too
hashwriter.Write(iv)
ctr := cipher.NewCTR(aes, iv)
// Decrypt using xor keystream the
// cipher input text is written to the
// hashwriter since the servers has no
// key and built it's hash using the
// encrypted text
for {
// return on cancel
select {
case <-cancelChan:
return ErrCancelled
default:
}
n, err := in.Read(buff)
if err != nil && err != io.EOF {
return err
}
if n != 0 {
outBuf := make([]byte, n)
ctr.XORKeyStream(outBuf, buff[:n])
out.Write(outBuf)
hashwriter.Write(buff[:n])
}
// Treat eof as stop condition, not as
// an error
if err == io.EOF {
break
}
}
return nil
}
// Return byte slice with base64 encoded file content
func fileToBase64(filename string, fh *os.File) ([]byte, error) {
s, err := os.Stat(filename)
if err != nil {
return nil, err
}
src := make([]byte, s.Size())
_, err = fh.Read(src)
if err != nil {
return nil, err
}
return encodeBase64(src), nil
}