diff options
Diffstat (limited to 'inform/crypto.go')
-rw-r--r-- | inform/crypto.go | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/inform/crypto.go b/inform/crypto.go new file mode 100644 index 0000000..90118c1 --- /dev/null +++ b/inform/crypto.go | |||
@@ -0,0 +1,88 @@ | |||
1 | package inform | ||
2 | |||
3 | import ( | ||
4 | "bytes" | ||
5 | "crypto/aes" | ||
6 | "crypto/cipher" | ||
7 | "crypto/rand" | ||
8 | "encoding/hex" | ||
9 | "errors" | ||
10 | ) | ||
11 | |||
12 | func Pad(src []byte, blockSize int) []byte { | ||
13 | padLen := blockSize - (len(src) % blockSize) | ||
14 | padText := bytes.Repeat([]byte{byte(padLen)}, padLen) | ||
15 | return append(src, padText...) | ||
16 | } | ||
17 | |||
18 | func Unpad(src []byte, blockSize int) ([]byte, error) { | ||
19 | srcLen := len(src) | ||
20 | paddingLen := int(src[srcLen-1]) | ||
21 | if paddingLen >= srcLen || paddingLen > blockSize { | ||
22 | return nil, errors.New("Padding size error") | ||
23 | } | ||
24 | return src[:srcLen-paddingLen], nil | ||
25 | } | ||
26 | |||
27 | func decodeHexKey(key string) (cipher.Block, error) { | ||
28 | decodedKey, err := hex.DecodeString(key) | ||
29 | if err != nil { | ||
30 | return nil, err | ||
31 | } | ||
32 | |||
33 | block, err := aes.NewCipher(decodedKey) | ||
34 | if err != nil { | ||
35 | return nil, err | ||
36 | } | ||
37 | |||
38 | return block, nil | ||
39 | } | ||
40 | |||
41 | func makeAESIV() ([]byte, error) { | ||
42 | iv := make([]byte, 16) | ||
43 | if _, err := rand.Read(iv); err != nil { | ||
44 | return nil, err | ||
45 | } | ||
46 | return iv, nil | ||
47 | } | ||
48 | |||
49 | // Returns ciphertext and IV, does not modify payload | ||
50 | func Encrypt(payload []byte, key string) ([]byte, []byte, error) { | ||
51 | ct := make([]byte, len(payload)) | ||
52 | copy(ct, payload) | ||
53 | ct = Pad(ct, aes.BlockSize) | ||
54 | |||
55 | iv, err := makeAESIV() | ||
56 | if err != nil { | ||
57 | return nil, nil, err | ||
58 | } | ||
59 | |||
60 | block, err := decodeHexKey(key) | ||
61 | if err != nil { | ||
62 | return nil, nil, err | ||
63 | } | ||
64 | |||
65 | mode := cipher.NewCBCEncrypter(block, iv) | ||
66 | mode.CryptBlocks(ct, ct) | ||
67 | |||
68 | return ct, iv, nil | ||
69 | } | ||
70 | |||
71 | func Decrypt(payload, iv []byte, key string) ([]byte, error) { | ||
72 | b := make([]byte, len(payload)) | ||
73 | |||
74 | block, err := decodeHexKey(key) | ||
75 | if err != nil { | ||
76 | return nil, err | ||
77 | } | ||
78 | |||
79 | mode := cipher.NewCBCDecrypter(block, iv) | ||
80 | mode.CryptBlocks(b, payload) | ||
81 | |||
82 | u, err := Unpad(b, aes.BlockSize) | ||
83 | if err != nil { | ||
84 | return nil, err | ||
85 | } | ||
86 | |||
87 | return u, nil | ||
88 | } | ||