1
2
3
4
5 package eax
6
7 import (
8 "bytes"
9 "crypto/aes"
10 "crypto/cipher"
11 "crypto/rand"
12 "encoding/hex"
13 mathrand "math/rand"
14 "testing"
15 )
16
17 const (
18 blockLength = 16
19 maxLength = 1 << 12
20 )
21
22 func TestEAXImplementsAEADInterface(t *testing.T) {
23 var eaxInstance eax
24 var aux interface{} = &eaxInstance
25 _, ok := aux.(cipher.AEAD)
26 if !ok {
27 t.Errorf("Error: EAX does not implement AEAD interface")
28 }
29 }
30
31
32 func TestEncryptDecryptEAXTestVectors(t *testing.T) {
33 for _, test := range testVectors {
34 adata, _ := hex.DecodeString(test.header)
35 key, _ := hex.DecodeString(test.key)
36 nonce, _ := hex.DecodeString(test.nonce)
37 targetPt, _ := hex.DecodeString(test.msg)
38 targetCt, _ := hex.DecodeString(test.ciphertext)
39 aesCipher, err := aes.NewCipher(key)
40 if err != nil {
41 t.Fatal(err)
42 }
43 eax, err := NewEAX(aesCipher)
44 if err != nil {
45 t.Fatal(err)
46 }
47
48 ct := eax.Seal(nil, nonce, targetPt, adata)
49 if !bytes.Equal(ct, targetCt) {
50 t.Errorf(
51 `Test vectors Encrypt error (ciphertexts don't match):
52 Got: %X
53 Want: %X`, ct, targetCt)
54 }
55 pt, err := eax.Open(nil, nonce, ct, adata)
56 if err != nil {
57 t.Errorf(
58 `Decrypt refused valid tag:
59 ciphertext %X
60 key %X
61 nonce %X
62 header %X`, ct, key, nonce, adata)
63 }
64 if !bytes.Equal(pt, targetPt) {
65 t.Errorf(
66 `Test vectors Decrypt error (plaintexts don't match):
67 Got: %X
68 Want: %X`, pt, targetPt)
69 }
70 }
71 }
72
73
74 func TestEncryptDecryptGoTestVectors(t *testing.T) {
75 for _, test := range randomVectors {
76 adata, _ := hex.DecodeString(test.header)
77 key, _ := hex.DecodeString(test.key)
78 nonce, _ := hex.DecodeString(test.nonce)
79 targetPt, _ := hex.DecodeString(test.plaintext)
80 targetCt, _ := hex.DecodeString(test.ciphertext)
81 aesCipher, err := aes.NewCipher(key)
82 if err != nil {
83 t.Fatal(err)
84 }
85 eax, err := NewEAX(aesCipher)
86 if err != nil {
87 t.Fatal(err)
88 }
89
90 ct := eax.Seal(nil, nonce, targetPt, adata)
91 if !bytes.Equal(ct, targetCt) {
92 t.Errorf(
93 `Test vectors Encrypt error (ciphertexts don't match):
94 Got: %X
95 Want: %X`, ct, targetCt)
96 }
97 pt, err := eax.Open(nil, nonce, ct, adata)
98 if err != nil {
99 t.Errorf(
100 `Decrypt refused valid tag:
101 ciphertext %X
102 key %X
103 nonce %X
104 header %X`, ct, key, nonce, adata)
105 }
106 if !bytes.Equal(pt, targetPt) {
107 t.Errorf(
108 `Test vectors Decrypt error (plaintexts don't match):
109 Got: %X
110 Want: %X`, pt, targetPt)
111 }
112 }
113 }
114
115 func TestNewEaxIncorrectNonceLength(t *testing.T) {
116 aesCipher, err := aes.NewCipher(make([]byte, 16))
117 if err != nil {
118 t.Fatal(err)
119 }
120 e, err := NewEAXWithNonceAndTagSize(aesCipher, 0, 16)
121 if err == nil || e != nil {
122 t.Errorf("EAX with nonceLength 0 was not rejected")
123 }
124 }
125
126 func TestSealIncorrectNonceLength(t *testing.T) {
127 aesCipher, err := aes.NewCipher(make([]byte, 16))
128 if err != nil {
129 t.Fatal(err)
130 }
131 e, err := NewEAXWithNonceAndTagSize(aesCipher, 16, 16)
132 if err != nil {
133 t.Fatal(err)
134 }
135 defer func() {
136 if r := recover(); r == nil {
137 t.Errorf("Eax.Seal didn't panic on exceedingly long nonce")
138 }
139 }()
140 longNonce := make([]byte, e.NonceSize()+1)
141 e.Seal(nil, longNonce, nil, nil)
142 }
143
144 func TestOpenIncorrectNonceLength(t *testing.T) {
145 aesCipher, err := aes.NewCipher(make([]byte, 16))
146 if err != nil {
147 t.Fatal(err)
148 }
149 e, err := NewEAXWithNonceAndTagSize(aesCipher, 16, 16)
150 if err != nil {
151 t.Fatal(err)
152 }
153 defer func() {
154 if r := recover(); r == nil {
155 t.Errorf("Eax.Open didn't panic on exceedingly long nonce")
156 }
157 }()
158 longNonce := make([]byte, e.NonceSize()+1)
159 _, err = e.Open(nil, longNonce, nil, nil)
160
161 if err != nil {
162 }
163 }
164
165 func TestOpenShortCiphertext(t *testing.T) {
166 aesCipher, err := aes.NewCipher(make([]byte, 16))
167 if err != nil {
168 t.Fatal(err)
169 }
170 e, err := NewEAXWithNonceAndTagSize(aesCipher, 16, 16)
171 if err != nil {
172 t.Fatal(err)
173 }
174 shortCt := make([]byte, e.Overhead()-1)
175 pt, err := e.Open(nil, nil, nil, shortCt)
176 if pt != nil || err == nil {
177 t.Errorf("Eax.Open processed an exceedingly short ciphertext")
178 }
179 }
180
181
182 func TestEncryptDecryptVectorsWithPreviousDataRandomizeSlow(t *testing.T) {
183
184 allowedKeyLengths := []int{16, 24, 32}
185 for _, keyLength := range allowedKeyLengths {
186 pt := make([]byte, mathrand.Intn(maxLength))
187 header := make([]byte, mathrand.Intn(maxLength))
188 key := make([]byte, keyLength)
189 nonce := make([]byte, 1+mathrand.Intn(blockLength))
190 previousData := make([]byte, mathrand.Intn(maxLength-2*blockLength))
191
192 itemsToRandomize := [][]byte{pt, header, key, nonce, previousData}
193 for _, item := range itemsToRandomize {
194 _, err := rand.Read(item)
195 if err != nil {
196 t.Fatal(err)
197 }
198 }
199 aesCipher, err := aes.NewCipher(key)
200 if err != nil {
201 t.Fatal(err)
202 }
203 eax, err := NewEAX(aesCipher)
204 if err != nil {
205 t.Fatal(err)
206 }
207 newData := eax.Seal(previousData, nonce, pt, header)
208 ct := newData[len(previousData):]
209 decrypted, err := eax.Open(nil, nonce, ct, header)
210 if err != nil {
211 t.Errorf(
212 `Decrypt refused valid tag (not displaying long output)`)
213 break
214 }
215 if !bytes.Equal(pt, decrypted) {
216 t.Errorf(
217 `Random Encrypt/Decrypt error (plaintexts don't match)`)
218 break
219 }
220 }
221 }
222
223 func TestRejectTamperedCiphertextRandomizeSlow(t *testing.T) {
224 pt := make([]byte, mathrand.Intn(maxLength))
225 header := make([]byte, mathrand.Intn(maxLength))
226 key := make([]byte, blockLength)
227 nonce := make([]byte, blockLength)
228 itemsToRandomize := [][]byte{pt, header, key, nonce}
229 for _, item := range itemsToRandomize {
230 _, err := rand.Read(item)
231 if err != nil {
232 t.Fatal(err)
233 }
234 }
235 aesCipher, err := aes.NewCipher(key)
236 if err != nil {
237 t.Fatal(err)
238 }
239 eax, err := NewEAX(aesCipher)
240 if err != nil {
241 t.Fatal(err)
242 }
243 ct := eax.Seal(nil, nonce, pt, header)
244
245 tampered := make([]byte, len(ct))
246 copy(tampered, ct)
247 for bytes.Equal(tampered, ct) {
248 tampered[mathrand.Intn(len(ct))] = byte(mathrand.Intn(len(ct)))
249 }
250 _, err = eax.Open(nil, nonce, tampered, header)
251 if err == nil {
252 t.Errorf(`Tampered ciphertext was not refused decryption`)
253 }
254 }
255
256 func TestParameters(t *testing.T) {
257 t.Run("Should return error on too long tagSize", func(st *testing.T) {
258 tagSize := blockLength + 1 + mathrand.Intn(12)
259 nonceSize := 1 + mathrand.Intn(16)
260 key := make([]byte, blockLength)
261 aesCipher, err := aes.NewCipher(key)
262 if err != nil {
263 t.Fatal(err)
264 }
265 _, err = NewEAXWithNonceAndTagSize(aesCipher, nonceSize, tagSize)
266 if err == nil {
267 st.Errorf("No error was given")
268 }
269 })
270 t.Run("Should not give error with allowed custom parameters", func(st *testing.T) {
271 key := make([]byte, blockLength)
272 nonceSize := mathrand.Intn(32) + 1
273 tagSize := 12 + mathrand.Intn(blockLength-11)
274 aesCipher, err := aes.NewCipher(key)
275 if err != nil {
276 t.Fatal(err)
277 }
278 _, err = NewEAXWithNonceAndTagSize(aesCipher, nonceSize, tagSize)
279 if err != nil {
280 st.Errorf("An error was returned")
281 }
282 })
283 }
284
285 func BenchmarkEncrypt(b *testing.B) {
286 headerLength := 16
287 pt := make([]byte, maxLength)
288 header := make([]byte, headerLength)
289 key := make([]byte, blockLength)
290 nonce := make([]byte, blockLength)
291 itemsToRandomize := [][]byte{pt, header, key, nonce}
292 for _, item := range itemsToRandomize {
293 _, err := rand.Read(item)
294 if err != nil {
295 b.Fatal(err)
296 }
297 }
298 aesCipher, err := aes.NewCipher(key)
299 if err != nil {
300 b.Fatal(err)
301 }
302 eax, err := NewEAX(aesCipher)
303 if err != nil {
304 b.Fatal(err)
305 }
306 for i := 0; i < b.N; i++ {
307 eax.Seal(nil, nonce, pt, header)
308 }
309 }
310
311 func BenchmarkDecrypt(b *testing.B) {
312 headerLength := 16
313 pt := make([]byte, maxLength)
314 header := make([]byte, headerLength)
315 key := make([]byte, blockLength)
316 nonce := make([]byte, blockLength)
317 itemsToRandomize := [][]byte{pt, header, key, nonce}
318 for _, item := range itemsToRandomize {
319 _, err := rand.Read(item)
320 if err != nil {
321 b.Fatal(err)
322 }
323 }
324 aesCipher, err := aes.NewCipher(key)
325 if err != nil {
326 b.Fatal(err)
327 }
328 eax, err := NewEAX(aesCipher)
329 if err != nil {
330 b.Fatal(err)
331 }
332 ct := eax.Seal(nil, nonce, pt, header)
333 for i := 0; i < b.N; i++ {
334 _, err := eax.Open(nil, nonce, ct, header)
335 if err != nil {
336 b.Fatal(err)
337 }
338 }
339 }
340
View as plain text