-
Notifications
You must be signed in to change notification settings - Fork 3
/
encrypter.go
145 lines (126 loc) · 3.62 KB
/
encrypter.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
package hypertrace
import (
"bytes"
"crypto/aes"
"crypto/cipher"
"crypto/rand"
"encoding/base64"
"fmt"
)
func encode(cyperText, iv []byte) (encoded []byte, err error) {
buff := &bytes.Buffer{}
err = buff.WriteByte(byte(len(cyperText)))
if err != nil {
return nil, fmt.Errorf("%w : encode error", err)
}
_, err = buff.Write(cyperText)
if err != nil {
return nil, fmt.Errorf("%w : encode error", err)
}
err = buff.WriteByte(byte(len(iv)))
if err != nil {
return nil, fmt.Errorf("%w : encode error", err)
}
_, err = buff.Write(iv)
if err != nil {
return nil, fmt.Errorf("%w : encode error", err)
}
return buff.Bytes(), nil
}
func decode(encoded []byte) (cyperText, iv []byte, err error) {
var cyperData, ivData []byte
buff := bytes.NewBuffer(encoded)
cypherLen, err := buff.ReadByte()
if err != nil {
return nil, nil, fmt.Errorf("%w : decode error during reading 1 byte from buffer to find out cypher len", err)
}
cyperData = make([]byte, cypherLen)
_, err = buff.Read(cyperData)
if err != nil {
return nil, nil, fmt.Errorf("%w : decode error during reading %d bytes of cypher data ", err, cypherLen)
}
ivLen, err := buff.ReadByte()
if err != nil {
return nil, nil, fmt.Errorf("%w : decode error during reading 1 byte from buffer to find out IV len", err)
}
ivData = make([]byte, ivLen)
_, err = buff.Read(ivData)
if err != nil {
return nil, nil, fmt.Errorf("%w : decode error during reading %d bytes of iv data", err, ivLen)
}
return cyperData, ivData, nil
}
func encrypt(data, key []byte) (cypherText, iv []byte, err error) {
if len(key) != 32 {
return nil, nil, fmt.Errorf("invalid key size %d, we expect 32", len(key))
}
iv = make([]byte, 12)
_, err = rand.Read(iv)
if err != nil {
return nil, nil, fmt.Errorf("%w : encrypt error", err)
}
aesBlock, err := aes.NewCipher(key)
if err != nil {
return nil, nil, fmt.Errorf("%w : encrypt error", err)
}
encrypter, err := cipher.NewGCM(aesBlock)
if err != nil {
return nil, nil, fmt.Errorf("%w : encrypt error", err)
}
cypherText = encrypter.Seal(nil, iv, data, nil)
return cypherText, iv, nil
}
func decrypt(cypherText, iv, key []byte) (data []byte, err error) {
if len(key) != 32 {
return nil, fmt.Errorf("decrypt error : invalid key size %d, we expect 32", len(key))
}
aesBlock, err := aes.NewCipher(key)
if err != nil {
return nil, fmt.Errorf("%w : decrypt error", err)
}
decryptor, err := cipher.NewGCM(aesBlock)
if err != nil {
return nil, fmt.Errorf("%w : decrypt error", err)
}
data, err = decryptor.Open(nil, iv, cypherText, nil)
if err != nil {
return nil, fmt.Errorf("%w : decryptor.Open error", err)
}
return data, err
}
func encryptAndEncode(data, key []byte) (crypted string, err error) {
cypherText, iv, err := encrypt(data, key)
if err != nil {
return "", fmt.Errorf("%w : encrypt-encode error", err)
}
encoded, err := encode(cypherText, iv)
if err != nil {
return "", fmt.Errorf("%w : encrypt-encode error", err)
}
return B64Encode(encoded), nil
}
func decodeAndDecrypt(crypted string, key []byte) (data []byte, err error) {
cypher, iv, err := decode(B64Decode(crypted))
if err != nil {
return nil, fmt.Errorf("%w : decode error when decoding base64 cryptext", err)
}
data, err = decrypt(cypher, iv, key)
if err != nil {
return nil, fmt.Errorf("%w : decrypt error", err)
}
return data, err
}
type SymetricKey struct {
Key string `json:"key"`
Iv string `json:"iv"`
}
func B64Encode(data []byte) string {
return base64.StdEncoding.EncodeToString(data)
}
func B64Decode(b64 string) []byte {
decoded, err := base64.StdEncoding.DecodeString(b64)
if err != nil {
panic(err.Error())
}
return decoded
}