-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathcrypter.go
100 lines (79 loc) · 2 KB
/
crypter.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
// AES-GCM for file chunks
package main
import (
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/binary"
"io"
)
// encryp plaintext and additonal data (can be nil) using key.
func encrypt(key, plaintext, ad []byte) ([]byte, []byte) {
// Init block
block, err := aes.NewCipher(key)
check(err)
// Random nonce
nonce := make([]byte, 12)
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
panic(err.Error())
}
// init cipher
aesgcm, err := cipher.NewGCM(block)
check(err)
// return nonce and ciphertext
return nonce, aesgcm.Seal(nil, nonce, plaintext, ad)
}
// Decrypt ciphertext using key, nonce and additonal data
func decrypt(key, nonce, ciphertext, ad []byte) []byte {
// Init block
block, err := aes.NewCipher(key)
check(err)
// init cipher
aesgcm, err := cipher.NewGCM(block)
check(err)
// decryption and integrity check
plaintext, err := aesgcm.Open(nil, nonce, ciphertext, ad)
check(err)
return plaintext
}
// chunker hook to encrypt data field of chunk
func encrypter(key []byte, pt, ct chan chunk) {
for {
// receive unencypted chunks
c := <-pt
if c.data == nil { // done
ct <- c // forward signal
break
}
// encode chunk id to byte array
ad := make([]byte, 8)
binary.LittleEndian.PutUint64(ad, c.id)
// encrypt data field, and add chunk id (for integrity check)
nonce, ciphertext := encrypt(key, c.data, ad)
c.data = append(nonce, ciphertext...)
// forward encrypted chunk
ct <- c
}
}
// hook to decrypt data field of chunks
func decrypter(key []byte, ct, pt chan chunk) {
for {
// receive encrypted chunks
c := <-ct
if c.data == nil { // done
pt <- c // forward signal
break
}
// split data into nonce and ciphertext
nonce := c.data[:12]
ciphertext := c.data[12:]
// encode chunk id to byte array
ad := make([]byte, 8)
binary.LittleEndian.PutUint64(ad, c.id)
// decrypt and integrity check data field
plaintext := decrypt(key, nonce, ciphertext, ad)
c.data = plaintext
// forward plaintext chunk
pt <- c
}
}