-
Notifications
You must be signed in to change notification settings - Fork 2
/
content_crypto.go
110 lines (94 loc) · 2.68 KB
/
content_crypto.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
package request
import (
"crypto/aes"
"crypto/cipher"
"encoding/json"
"fmt"
"github.com/gildas/go-errors"
)
type CryptoAlgorithm uint
const (
NONE CryptoAlgorithm = iota
AESCTR
)
func (algorithm CryptoAlgorithm) String() string {
algorithms := [...]string{"NONE", "AESCTR"}
if int(algorithm) > len(algorithms) {
return fmt.Sprintf("Unknown %d", algorithm)
}
return algorithms[algorithm]
}
func CryptoAlgorithmFromString(algorithm string) (CryptoAlgorithm, error) {
switch algorithm {
case "NONE":
return NONE, nil
case "AESCTR":
return AESCTR, nil
}
return NONE, errors.ArgumentInvalid.With("algorithm", algorithm)
}
func (algorithm CryptoAlgorithm) MarshalJSON() ([]byte, error) {
return []byte(fmt.Sprintf("\"%s\"", algorithm.String())), nil
}
func (algorithm *CryptoAlgorithm) UnmarshalJSON(data []byte) (err error) {
var value string
if err = json.Unmarshal(data, &value); err != nil {
return errors.JSONUnmarshalError.WrapIfNotMe(err)
}
*algorithm, err = CryptoAlgorithmFromString(value)
return errors.JSONUnmarshalError.Wrap(err)
}
func (content Content) Decrypt(algorithm CryptoAlgorithm, key []byte) (*Content, error) {
switch algorithm {
case NONE:
return &content, nil
case AESCTR:
return content.DecryptWithAESCTR(key)
}
return nil, errors.InvalidType.With(algorithm.String())
}
func (content Content) DecryptWithAESCTR(key []byte) (*Content, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, errors.WrapErrors(errors.ArgumentInvalid.With("key", key), err)
}
decrypted := Content{
Type: content.Type,
Name: content.Name,
URL: content.URL,
Headers: content.Headers,
Cookies: content.Cookies,
Length: content.Length,
Data: make([]byte, len(content.Data)),
}
stream := cipher.NewCTR(block, make([]byte, aes.BlockSize))
stream.XORKeyStream(decrypted.Data, content.Data)
return &decrypted, nil
}
func (content Content) Encrypt(algorithm CryptoAlgorithm, key []byte) (*Content, error) {
switch algorithm {
case NONE:
return &content, nil
case AESCTR:
return content.EncryptWithAESCTR(key)
}
return nil, errors.InvalidType.With(algorithm.String())
}
func (content Content) EncryptWithAESCTR(key []byte) (*Content, error) {
block, err := aes.NewCipher(key)
if err != nil {
return nil, errors.WrapErrors(errors.ArgumentInvalid.With("key", key), err)
}
encrypted := Content{
Type: content.Type,
Name: content.Name,
URL: content.URL,
Headers: content.Headers,
Cookies: content.Cookies,
Length: content.Length,
Data: make([]byte, len(content.Data)),
}
stream := cipher.NewCTR(block, make([]byte, aes.BlockSize))
stream.XORKeyStream(encrypted.Data, content.Data)
return &encrypted, nil
}