-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsecurefile.go
More file actions
133 lines (105 loc) · 2.39 KB
/
securefile.go
File metadata and controls
133 lines (105 loc) · 2.39 KB
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
package securefile
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"crypto/sha1"
"encoding/hex"
"io"
"os"
"golang.org/x/crypto/pbkdf2"
)
// Encrypt encrypts a file using AES-GCM.
func Encrypt(source string, password []byte) (bool, error) {
// we need file to exist
if _, err := os.Stat(source); os.IsNotExist(err) {
return false, err
}
// read file
plaintext, err := os.ReadFile(source)
if err != nil {
return false, err
}
// generate salt
key := password
nonce := make([]byte, 12)
if _, err := io.ReadFull(rand.Reader, nonce); err != nil {
return false, err
}
// generate key
dk := pbkdf2.Key(key, nonce, 4096, 32, sha1.New)
block, err := aes.NewCipher(dk)
if err != nil {
return false, err
}
// generate gcm cipher
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return false, err
}
// generate ciphertext
ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil)
// Append the nonce to the end of file
ciphertext = append(ciphertext, nonce...)
// build encrypted file
f, err := os.Create(source)
if err != nil {
return false, err
}
// write to file encrypted content
_, err = io.Copy(f, bytes.NewReader(ciphertext))
if err != nil {
return false, err
}
return true, nil
}
// Decrypt decrypts a file using AES-GCM.
func Decrypt(source string, password []byte) (bool, error) {
// get file information, we need to know if file exists
if _, err := os.Stat(source); os.IsNotExist(err) {
return false, err
}
// read file
ciphertext, err := os.ReadFile(source)
if err != nil {
return false, err
}
// generate salt
key := password
salt := ciphertext[len(ciphertext)-12:]
str := hex.EncodeToString(salt)
// get decoded string
nonce, err := hex.DecodeString(str)
if err != nil {
return false, err
}
// generate key
dk := pbkdf2.Key(key, nonce, 4096, 32, sha1.New)
// generate block
block, err := aes.NewCipher(dk)
if err != nil {
return false, err
}
// generate gcm cipher
aesgcm, err := cipher.NewGCM(block)
if err != nil {
return false, err
}
// generate plaintext
plaintext, err := aesgcm.Open(nil, nonce, ciphertext[:len(ciphertext)-12], nil)
if err != nil {
return false, err
}
// build decrypted file
f, err := os.Create(source)
if err != nil {
return false, err
}
// write to file decrypted content
_, err = io.Copy(f, bytes.NewReader(plaintext))
if err != nil {
return false, err
}
return true, nil
}