-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathencryption.go
238 lines (209 loc) · 6.01 KB
/
encryption.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
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
package main
import (
"code.google.com/p/go.crypto/pbkdf2"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/rsa"
"crypto/sha256"
"crypto/sha512"
"fmt"
"io"
"os"
// "path/filepath"
)
// TODO: ADD MAKING PADDING AND STRIPPING IT AS WELL AS PUTTING THE BASE IV ONTO THE FILE
func ReadAndEncrypt(filename string) {
// read a file in chunks, encrypt, send!
// Errors here should maybe result in pushing those event back onto the queue?
// or push them onto an error channel so that they can be handled else where?
}
// test function to see if the symmetric RSA encryption worked.
func TestCrypto() {
key := createRSA(2048)
message := []byte("this is a test message")
fmt.Println(len(message))
encMessage := encryptRSA(&key.PublicKey, message)
decMessage := decryptRSA(key, encMessage)
fmt.Println("message is: {", string(message[:]), "}\ndecrypted message is: {", string(decMessage[:]), "}")
if len(message) == len(decMessage) {
fmt.Printf("It worked!\n")
}
return
}
// creates a unique(relying on crypto/rand) AES key for the per file keys
func CreateAES() []byte {
key := make([]byte, 32)
_, err := rand.Read(key)
if err != nil {
fmt.Println("ERROR:", err)
}
return key
}
// creates the master AES key for the user based on their password.
func createUserAES(password string) ([]byte, []byte) {
salt := make([]byte, 10) // TODO: make 10 a constant variable
_, err := rand.Read(salt)
if err != nil {
fmt.Println("ERROR:", err)
}
key := pbkdf2.Key([]byte(password), salt, 5000, 32, sha256.New) // TODO: make 5000 a const var
return key, salt
}
// create an RSA key when given a size.
// TODO: add in customization based on password.
func createRSA(size int) *rsa.PrivateKey {
key, err := rsa.GenerateKey(rand.Reader, size)
if err != nil {
fmt.Printf("error occured generating the key:\n")
}
return key
}
// encrypts a given message with a provided RSA public key.
// the label must be the same for the encryption and decryption for it to work.
func encryptRSA(pub *rsa.PublicKey, message []byte) []byte {
label := make([]byte, 10)
encMessage, err := rsa.EncryptOAEP(sha512.New(), rand.Reader, pub, message, label)
fmt.Println(encMessage)
if err != nil {
fmt.Println("encryption failed!: ", err)
}
return encMessage
}
// decrypts a given message with the provided RSA private key
// the label must be the same for the encryption and decryption for it to work.
func decryptRSA(private *rsa.PrivateKey, ciphertext []byte) []byte {
label := make([]byte, 10)
message, err := rsa.DecryptOAEP(sha512.New(), rand.Reader, private, ciphertext, label)
if err != nil {
fmt.Println("decryption failed!: ", err)
}
return message
}
func EncryptFile(filepath string, key []byte) {
plainText, err := os.Open(filepath)
if err != nil {
fmt.Println("ERROR:", err)
}
defer plainText.Close()
cipherText, err := os.Create(filepath + ".aes")
if err != nil {
fmt.Println("ERROR:", err)
}
defer cipherText.Close()
iv := make([]byte, 16) // AES const
if _, err = rand.Read(iv); err != nil {
fmt.Println("ERROR:", err)
}
cipherText.Write(iv)
fmt.Println("iv=", iv[:])
encBlock := make([]byte, 16) // change to AES const for non-hardcoding
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println("ERROR:", err)
}
mode := cipher.NewCBCEncrypter(block, iv)
// we now have the encrypter, we can loop over the file contents now
stats, err := plainText.Stat()
if err != nil {
fmt.Println("ERROR:", err)
}
//var fileRead int64 = 0
pad := 16 - (stats.Size() % 16) //AES const
if pad == 0 {
pad = 16
}
message := make([]byte, 16) // AES const
endFile := false
for !endFile { //stats.Size() >= fileRead { // AES const
//read in file, check for end, if so pad
_, err := plainText.Read(message)
//fileRead += 16 // AES const
if err != nil && err != io.EOF {
fmt.Println("ERROR:", err) // if delete close down encryption
}
if err == io.EOF {
endFile = true
// we have to pad
for i := pad; i > 0; i-- {
message[16-i] = byte(pad)
}
}
fmt.Println("message =", message[:])
// encrypt the message slice
mode.CryptBlocks(encBlock, message)
fmt.Println("encrypt=", encBlock[:])
//write and reset the message slice
cipherText.Write(encBlock)
}
}
func DecryptFile(filepath string, key []byte) {
fmt.Println()
cipherText, err := os.Open(filepath)
if err != nil {
fmt.Println("ERROR:", err)
}
defer cipherText.Close()
plainText, err := os.Create(filepath + ".dec")
if err != nil {
fmt.Println("ERROR:", err)
}
defer plainText.Close()
iv := make([]byte, 16) //AES const
_, err = cipherText.Read(iv)
fmt.Println("iv=", iv[:])
if err != nil {
fmt.Println("ERROR:", err)
}
encBlock := make([]byte, 16) // AES const
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println("ERROR:", err)
}
mode := cipher.NewCBCDecrypter(block, iv)
// we have decrypter, can loop over file contents now
// know size so can not get EOF'd
stats, err := cipherText.Stat()
if err != nil {
fmt.Println("ERROR:", err)
}
var ReadAmt int64 = 16
message := make([]byte, 16)
for ReadAmt != stats.Size() {
//read in file, decrypt, check for end, if so strip padding
if _, err := cipherText.Read(encBlock); err != nil {
fmt.Println("ERROR:", err)
}
ReadAmt += 16 // AES const
mode.CryptBlocks(message, encBlock)
//check for end, if so strip pad
fmt.Println("encrypt=", encBlock[:])
fmt.Println("message=", message[:])
if ReadAmt == stats.Size() {
pad := message[15]
message = message[:16-pad]
}
plainText.Write(message)
}
}
func encryptAES(key []byte, iv []byte, message []byte) []byte {
encBlock := make([]byte, 16)
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println("ERROR:", err)
}
mode := cipher.NewCBCEncrypter(block, iv)
//loop now
mode.CryptBlocks(encBlock, message)
return encBlock
}
func decryptAES(key []byte, iv []byte, encBlock []byte) []byte {
decBlock := make([]byte, 16)
block, err := aes.NewCipher(key)
if err != nil {
fmt.Println("ERROR:", err)
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(decBlock, encBlock)
return decBlock
}