forked from upstartmobile/simpleaes
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimpleaes.go
115 lines (106 loc) · 3.02 KB
/
simpleaes.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
// Make encryption in Go easy
package simpleaes
import (
"crypto/aes"
"crypto/cipher"
"io"
)
type Aes struct {
enc, dec cipher.BlockMode
}
// Creates a new encryption/decryption object
// with a given key of a given size
// (16, 24 or 32 for AES-128, AES-192 and AES-256 respectively,
// as per http://golang.org/pkg/crypto/aes/#NewCipher)
//
// The key will be padded to the given size if needed.
// An IV is created as a series of NULL bytes of necessary length
// when there is no iv string passed as 3rd value to function.
func New(size int, key string, more ...string) (*Aes, error) {
padded := make([]byte, size)
copy(padded, []byte(key))
aes, err := aes.NewCipher(padded)
if err != nil {
return nil, err
}
var iv []byte
if len(more) > 0 {
iv = []byte(more[0])[0:aes.BlockSize()]
} else {
iv = make([]byte, aes.BlockSize())
}
enc := cipher.NewCBCEncrypter(aes, iv)
dec := cipher.NewCBCDecrypter(aes, iv)
return &Aes{enc, dec}, nil
}
func (me *Aes) padSlice(src []byte) []byte {
// src must be a multiple of block size
bs := me.enc.BlockSize()
mult := int((len(src) / bs) + 1)
leng := bs * mult
src_padded := make([]byte, leng)
copy(src_padded, src)
return src_padded
}
// Encrypt a slice of bytes, producing a new, freshly allocated slice
//
// Source will be padded with null bytes if necessary
func (me *Aes) Encrypt(src []byte) []byte {
if len(src)%me.enc.BlockSize() != 0 {
src = me.padSlice(src)
}
dst := make([]byte, len(src))
me.enc.CryptBlocks(dst, src)
return dst
}
// Encrypt blocks from reader, write results into writer
func (me *Aes) EncryptStream(reader io.Reader, writer io.Writer) error {
for {
buf := make([]byte, me.enc.BlockSize())
_, err := io.ReadFull(reader, buf)
if err != nil {
if err == io.EOF {
break
} else if err == io.ErrUnexpectedEOF {
// nothing
} else {
return err
}
}
me.enc.CryptBlocks(buf, buf)
if _, err = writer.Write(buf); err != nil {
return err
}
}
return nil
}
// Decrypt a slice of bytes, producing a new, freshly allocated slice
//
// Source will be padded with null bytes if necessary
func (me *Aes) Decrypt(src []byte) []byte {
if len(src)%me.dec.BlockSize() != 0 {
src = me.padSlice(src)
}
dst := make([]byte, len(src))
me.dec.CryptBlocks(dst, src)
return dst
}
// Decrypt blocks from reader, write results into writer
func (me *Aes) DecryptStream(reader io.Reader, writer io.Writer) error {
buf := make([]byte, me.dec.BlockSize())
for {
_, err := io.ReadFull(reader, buf)
if err != nil {
if err == io.EOF {
break
} else {
return err
}
}
me.dec.CryptBlocks(buf, buf)
if _, err = writer.Write(buf); err != nil {
return err
}
}
return nil
}