/
aes.go
78 lines (71 loc) · 2.07 KB
/
aes.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
package main
import (
"crypto/aes"
"crypto/cipher"
"errors"
)
// encryptAES enrypts plaintext input with passed key, IV and mode in AES block cipher;
// and returns ciphertext output
func encryptAES(input []byte, output []byte, key, iv []byte, mode Mode) error {
block, err := aes.NewCipher(key)
if err != nil {
return errors.New("Couldn't create block cipher.")
}
// Prepend IV to ciphertext.
// Generate IV randomly if it is not passed
if iv == nil {
if iv = generateIV(aes.BlockSize); iv == nil {
return errors.New("Couldn't create random initialization vector (IV).")
}
}
copy(output, iv)
switch mode {
case CBC:
if len(input)%aes.BlockSize != 0 {
input = addPadding(input, aes.BlockSize)
}
mode := cipher.NewCBCEncrypter(block, iv)
mode.CryptBlocks(output[aes.BlockSize:], input)
case CFB:
mode := cipher.NewCFBEncrypter(block, iv)
mode.XORKeyStream(output[aes.BlockSize:], input)
case CTR:
mode := cipher.NewCTR(block, iv)
mode.XORKeyStream(output[aes.BlockSize:], input)
case OFB:
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(output[aes.BlockSize:], input)
}
return nil
}
// decryptAES derypts ciphertext input with passed key and mode (IV is contained in input)
// in AES block cipher; and returns plaintext output
func decryptAES(input []byte, output []byte, key []byte, mode Mode) error {
block, err := aes.NewCipher(key)
if err != nil {
return errors.New("Couldn't create block cipher.")
}
if len(input) < aes.BlockSize {
return errors.New("Ciphertext too short.")
}
iv := input[:aes.BlockSize]
ciphertext := input[aes.BlockSize:]
switch mode {
case CBC:
if len(input)%aes.BlockSize != 0 {
return errors.New("Ciphertext doesn't satisfy CBC-mode requirements.")
}
mode := cipher.NewCBCDecrypter(block, iv)
mode.CryptBlocks(output, ciphertext)
case CFB:
mode := cipher.NewCFBDecrypter(block, iv)
mode.XORKeyStream(output, ciphertext)
case CTR:
mode := cipher.NewCTR(block, iv)
mode.XORKeyStream(output, ciphertext)
case OFB:
mode := cipher.NewOFB(block, iv)
mode.XORKeyStream(output, ciphertext)
}
return nil
}