1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.crypto.cipher;
19
20 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
21 import static org.junit.jupiter.api.Assertions.assertEquals;
22 import static org.junit.jupiter.api.Assertions.assertThrows;
23
24 import java.nio.ByteBuffer;
25 import java.security.Key;
26 import java.util.Arrays;
27 import java.util.Properties;
28 import java.util.Random;
29
30 import javax.crypto.AEADBadTagException;
31 import javax.crypto.Cipher;
32 import javax.crypto.spec.GCMParameterSpec;
33 import javax.xml.bind.DatatypeConverter;
34
35 import org.apache.commons.crypto.utils.AES;
36 import org.apache.commons.crypto.utils.Utils;
37 import org.junit.jupiter.api.BeforeEach;
38 import org.junit.jupiter.api.Test;
39
40
41 public class GcmCipherTest {
42
43 private static final String GCM_NO_PADDING = "AES/GCM/NoPadding";
44 Properties props;
45 String cipherClass;
46 String transformation = GCM_NO_PADDING;
47
48 private String[] kHex;
49 private String[] pHex;
50 private String[] ivHex;
51 private String[] aadHex;
52 private String[] cHex;
53 private String[] tHex;
54
55 private void initTestData() {
56
57 final int casesNumber = 4;
58
59 kHex = new String[casesNumber];
60 pHex = new String[casesNumber];
61 ivHex = new String[casesNumber];
62 aadHex = new String[casesNumber];
63 cHex = new String[casesNumber];
64 tHex = new String[casesNumber];
65
66
67
68
69
70
71
72
73 kHex[0] = "00000000000000000000000000000000";
74 pHex[0] = "00000000000000000000000000000000";
75 ivHex[0] = "000000000000000000000000";
76 aadHex[0] = "";
77 cHex[0] = "0388dace60b6a392f328c2b971b2fe78";
78 tHex[0] = "ab6e47d42cec13bdf53a67b21257bddf";
79
80
81
82
83
84
85 kHex[1] = "feffe9928665731c6d6a8f9467308308";
86 pHex[1] = "d9313225f88406e5a55909c5aff5269a"
87 + "86a7a9531534f7da2e4c303d8a318a72"
88 + "1c3c0c95956809532fcf0e2449a6b525"
89 + "b16aedf5aa0de657ba637b39";
90 ivHex[1] = "cafebabefacedbaddecaf888";
91 aadHex[1] = "feedfacedeadbeeffeedfacedeadbeef"
92 + "abaddad2";
93 cHex[1] = "42831ec2217774244b7221b784d0d49c"
94 + "e3aa212f2c02a4e035c17e2329aca12e"
95 + "21d514b25466931c7d8f6a5aac84aa05"
96 + "1ba30b396a0aac973d58e091";
97 tHex[1] = "5bc94fbc3221a5db94fae95ae7121a47";
98
99
100
101
102
103
104 kHex[2] = "feffe9928665731c6d6a8f9467308308";
105 pHex[2] = "d9313225f88406e5a55909c5aff5269a"
106 + "86a7a9531534f7da2e4c303d8a318a72"
107 + "1c3c0c95956809532fcf0e2449a6b525"
108 + "b16aedf5aa0de657ba637b39";
109 ivHex[2] ="cafebabefacedbad";
110 aadHex[2]="feedfacedeadbeeffeedfacedeadbeef"
111 + "abaddad2";
112 cHex[2] = "61353b4c2806934a777ff51fa22a4755"
113 + "699b2a714fcdc6f83766e5f97b6c7423"
114 + "73806900e49f24b22b097544d4896b42"
115 + "4989b5e1ebac0f07c23f4598";
116 tHex[2] = "3612d2e79e3b0785561be14aaca2fccb";
117
118
119
120
121
122
123 kHex[3] = "feffe9928665731c6d6a8f9467308308";
124 pHex[3] = "d9313225f88406e5a55909c5aff5269a"
125 + "86a7a9531534f7da2e4c303d8a318a72"
126 + "1c3c0c95956809532fcf0e2449a6b525"
127 + "b16aedf5aa0de657ba637b39";
128 ivHex[3] = "9313225df88406e555909c5aff5269aa"
129 + "6a7a9538534f7da1e4c303d2a318a728"
130 + "c3c0c95156809539fcf0e2429a6b5254"
131 + "16aedbf5a0de6a57a637b39b";
132 aadHex[3] = "feedfacedeadbeeffeedfacedeadbeef"
133 + "abaddad2";
134 cHex[3] = "8ce24998625615b603a033aca13fb894"
135 + "be9112a5c3a211a8ba262a3cca7e2ca7"
136 + "01e4a9a4fba43c90ccdcb281d48c7c6f"
137 + "d62875d2aca417034c34aee5";
138 tHex[3] = "619cc5aefffe0bfa462af43c1699d050";
139 }
140
141 @BeforeEach
142 public void setup() {
143
144 cipherClass = OpenSslCipher.class.getName();
145
146 props = new Properties();
147 props.setProperty(CryptoCipherFactory.CLASSES_KEY,
148 cipherClass);
149 initTestData();
150 }
151
152 private void testGcmArbitraryLengthUpdate(final String kHex, final String pHex, final String ivHex, final String aadHex,
153 final String cHex, final String tHex) throws Exception {
154
155 final byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex);
156 final byte[] input = DatatypeConverter.parseHexBinary(pHex);
157 final byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex);
158 final byte[] aad = DatatypeConverter.parseHexBinary(aadHex);
159 final byte[] expectedOutput = DatatypeConverter.parseHexBinary(cHex+tHex);
160
161 final byte[] encOutput = new byte[expectedOutput.length];
162 final byte[] decOutput = new byte[input.length];
163
164 final Random r = new Random();
165
166 int partLen;
167 int len;
168 try (final CryptoCipher enc = Utils.getCipherInstance(transformation, props)) {
169 final Key key = AES.newSecretKeySpec(keyBytes);
170 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
171 enc.init(Cipher.ENCRYPT_MODE, key, iv);
172 if (aad.length > 0) {
173 final int len1 = r.nextInt(aad.length);
174 final byte[] aad1 = Arrays.copyOfRange(aad, 0, len1);
175 final byte[] aad2 = Arrays.copyOfRange(aad, len1, aad.length);
176 enc.updateAAD(aad1);
177 enc.updateAAD(aad2);
178 }
179
180 partLen = r.nextInt(input.length);
181 len = enc.update(input, 0, partLen, encOutput, 0);
182 assertEquals(partLen, len);
183 len = enc.doFinal(input, partLen, input.length - partLen, encOutput, partLen);
184 assertEquals((input.length + (iv.getTLen() >> 3) - partLen), len);
185
186 assertArrayEquals(expectedOutput, encOutput);
187 }
188
189
190 try (final CryptoCipher dec = Utils.getCipherInstance(transformation, props)) {
191 dec.init(Cipher.DECRYPT_MODE, AES.newSecretKeySpec(keyBytes), new GCMParameterSpec(128, ivBytes));
192 if (aad.length > 0) {
193 final int len1 = r.nextInt(aad.length);
194 final byte[] aad1 = Arrays.copyOfRange(aad, 0, len1);
195 final byte[] aad2 = Arrays.copyOfRange(aad, len1, aad.length);
196 dec.updateAAD(aad1);
197 dec.updateAAD(aad2);
198 }
199 final byte[] decInput = encOutput;
200 partLen = r.nextInt(input.length);
201 len = dec.update(decInput, 0, partLen, decOutput, 0);
202 assertEquals(len, 0);
203 len = dec.doFinal(decInput, partLen, decInput.length - partLen, decOutput, 0);
204 assertEquals(input.length, len);
205
206 assertArrayEquals(input, decOutput);
207 }
208 }
209
210 private void testGcmByteBuffer(final String kHex, final String pHex, final String ivHex, final String aadHex,
211 final String cHex, final String tHex) throws Exception {
212
213 final byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex);
214 final byte[] plainText = DatatypeConverter.parseHexBinary(pHex);
215 final byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex);
216 final byte[] aad = DatatypeConverter.parseHexBinary(aadHex);
217 final byte[] cipherText = DatatypeConverter.parseHexBinary(cHex+tHex);
218
219 final byte[] encOutput = new byte[cipherText.length];
220 final byte[] decOutput = new byte[plainText.length];
221
222 final ByteBuffer bfAAD = ByteBuffer.allocateDirect(aad.length);
223 bfAAD.put(aad);
224
225 final ByteBuffer bfPlainText;
226 final ByteBuffer bfCipherText;
227 bfPlainText = ByteBuffer.allocateDirect(plainText.length);
228 bfCipherText = ByteBuffer.allocateDirect(encOutput.length);
229
230
231 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
232 final Key key = AES.newSecretKeySpec(keyBytes);
233 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
234 c.init(Cipher.ENCRYPT_MODE, key, iv);
235
236 bfAAD.flip();
237 c.updateAAD(bfAAD);
238
239 bfPlainText.put(plainText);
240 bfPlainText.flip();
241 bfCipherText.position(0);
242
243 c.doFinal(bfPlainText, bfCipherText);
244
245 bfCipherText.flip();
246 bfCipherText.get(encOutput);
247 assertArrayEquals(cipherText, encOutput);
248 }
249
250
251 try (final CryptoCipher dec = Utils.getCipherInstance(transformation, props)) {
252 dec.init(Cipher.DECRYPT_MODE, AES.newSecretKeySpec(keyBytes), new GCMParameterSpec(128, ivBytes));
253 bfAAD.flip();
254 dec.updateAAD(bfAAD);
255 bfCipherText.clear();
256 bfPlainText.clear();
257 bfCipherText.put(cipherText);
258 bfCipherText.flip();
259 dec.doFinal(bfCipherText, bfPlainText);
260 bfPlainText.flip();
261 bfPlainText.get(decOutput);
262 assertArrayEquals(plainText, decOutput);
263 }
264 }
265
266 private void testGcmDecryption(final String kHex, final String pHex, final String ivHex, final String aadHex,
267 final String cHex, final String tHex) throws Exception {
268
269 final byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex);
270 final byte[] plainBytes = DatatypeConverter.parseHexBinary(pHex);
271 final byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex);
272
273 final byte[] aad = DatatypeConverter.parseHexBinary(aadHex);
274 final byte[] cipherBytes = DatatypeConverter.parseHexBinary(cHex+tHex);
275
276 final byte[] input = cipherBytes;
277 final byte[] output = new byte[plainBytes.length];
278
279 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
280
281 final Key key = AES.newSecretKeySpec(keyBytes);
282
283 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
284 c.init(Cipher.DECRYPT_MODE, key, iv);
285 c.updateAAD(aad);
286 c.doFinal(input, 0, input.length, output, 0);
287
288 assertArrayEquals(plainBytes, output);
289 }
290 }
291
292 private void testGcmEncryption(final String kHex, final String pHex, final String ivHex, final String aadHex,
293 final String cHex, final String tHex) throws Exception {
294
295 final byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex);
296 final byte[] input = DatatypeConverter.parseHexBinary(pHex);
297 final byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex);
298 final byte[] aad = DatatypeConverter.parseHexBinary(aadHex);
299 final byte[] expectedOutput = DatatypeConverter.parseHexBinary(cHex+tHex);
300
301 final byte[] output = new byte[expectedOutput.length];
302
303 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
304
305 final Key key = AES.newSecretKeySpec(keyBytes);
306
307 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
308 c.init(Cipher.ENCRYPT_MODE, key, iv);
309 c.updateAAD(aad);
310
311 c.doFinal(input, 0, input.length, output, 0);
312
313 assertArrayEquals(expectedOutput, output);
314 }
315 }
316
317
318
319
320
321
322 @Test
323 public void testGcmNistCase2() throws Exception {
324
325
326
327
328
329 final String kHex = "00000000000000000000000000000000";
330 final String pHex = "00000000000000000000000000000000";
331 final String ivHex = "000000000000000000000000";
332 final String aadHex = "";
333
334 final String cHex = "0388dace60b6a392f328c2b971b2fe78";
335 final String tHex = "ab6e47d42cec13bdf53a67b21257bddf";
336
337 testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
338 testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
339 testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex);
340 testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex);
341 testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex);
342 }
343
344 @Test
345 public void testGcmNistCase4() throws Exception {
346
347
348
349
350
351 final String kHex = "feffe9928665731c6d6a8f9467308308";
352 final String pHex = "d9313225f88406e5a55909c5aff5269a"
353 + "86a7a9531534f7da2e4c303d8a318a72"
354 + "1c3c0c95956809532fcf0e2449a6b525"
355 + "b16aedf5aa0de657ba637b39";
356 final String ivHex = "cafebabefacedbaddecaf888";
357 final String aadHex = "feedfacedeadbeeffeedfacedeadbeef"
358 + "abaddad2";
359
360 final String cHex = "42831ec2217774244b7221b784d0d49c"
361 + "e3aa212f2c02a4e035c17e2329aca12e"
362 + "21d514b25466931c7d8f6a5aac84aa05"
363 + "1ba30b396a0aac973d58e091";
364 final String tHex = "5bc94fbc3221a5db94fae95ae7121a47";
365
366 testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
367 testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
368 testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex);
369 testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex);
370 testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex);
371 }
372
373 @Test
374 public void testGcmNistCase5() throws Exception {
375
376
377
378
379
380 final String kHex = "feffe9928665731c6d6a8f9467308308";
381
382 final String pHex = "d9313225f88406e5a55909c5aff5269a"
383 + "86a7a9531534f7da2e4c303d8a318a72"
384 + "1c3c0c95956809532fcf0e2449a6b525"
385 + "b16aedf5aa0de657ba637b39";
386
387 final String ivHex ="cafebabefacedbad";
388
389 final String aadHex="feedfacedeadbeeffeedfacedeadbeef"
390 + "abaddad2";
391
392 final String cHex = "61353b4c2806934a777ff51fa22a4755"
393 + "699b2a714fcdc6f83766e5f97b6c7423"
394 + "73806900e49f24b22b097544d4896b42"
395 + "4989b5e1ebac0f07c23f4598";
396
397 final String tHex = "3612d2e79e3b0785561be14aaca2fccb";
398
399 testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
400 testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
401 testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex);
402 testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex);
403 testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex);
404 }
405
406 @Test
407 public void testGcmNistCase6() throws Exception {
408
409
410
411
412
413 final String kHex = "feffe9928665731c6d6a8f9467308308";
414
415 final String pHex = "d9313225f88406e5a55909c5aff5269a"
416 + "86a7a9531534f7da2e4c303d8a318a72"
417 + "1c3c0c95956809532fcf0e2449a6b525"
418 + "b16aedf5aa0de657ba637b39";
419
420 final String ivHex ="9313225df88406e555909c5aff5269aa"
421 + "6a7a9538534f7da1e4c303d2a318a728"
422 + "c3c0c95156809539fcf0e2429a6b5254"
423 + "16aedbf5a0de6a57a637b39b";
424
425 final String aadHex="feedfacedeadbeeffeedfacedeadbeef"
426 + "abaddad2";
427
428 final String cHex = "8ce24998625615b603a033aca13fb894"
429 + "be9112a5c3a211a8ba262a3cca7e2ca7"
430 + "01e4a9a4fba43c90ccdcb281d48c7c6f"
431 + "d62875d2aca417034c34aee5";
432
433 final String tHex = "619cc5aefffe0bfa462af43c1699d050";
434
435 testGcmEncryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
436 testGcmDecryption(kHex, pHex, ivHex, aadHex, cHex, tHex);
437 testGcmByteBuffer(kHex, pHex, ivHex, aadHex, cHex, tHex);
438 testGcmReturnDataAfterTagVerified(kHex, pHex, ivHex, aadHex, cHex, tHex);
439 testGcmArbitraryLengthUpdate(kHex, pHex, ivHex, aadHex, cHex, tHex);
440 }
441
442 @Test
443 public void testGcmNistCases() throws Exception {
444 for(int i = 0; i < kHex.length; i++) {
445 testGcmEncryption(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]);
446 testGcmDecryption(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]);
447 testGcmByteBuffer(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]);
448 testGcmReturnDataAfterTagVerified(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]);
449 testGcmArbitraryLengthUpdate(kHex[i], pHex[i], ivHex[i], aadHex[i], cHex[i], tHex[i]);
450 }
451 }
452
453 private void testGcmReturnDataAfterTagVerified(final String kHex, final String pHex, final String ivHex, final String aadHex,
454 final String cHex, final String tHex) throws Exception {
455
456 final byte[] keyBytes = DatatypeConverter.parseHexBinary(kHex);
457 final byte[] plainBytes = DatatypeConverter.parseHexBinary(pHex);
458 final byte[] ivBytes = DatatypeConverter.parseHexBinary(ivHex);
459
460 final byte[] aad = DatatypeConverter.parseHexBinary(aadHex);
461 final byte[] cipherBytes = DatatypeConverter.parseHexBinary(cHex+tHex);
462
463 final byte[] input = cipherBytes;
464 final byte[] output = new byte[plainBytes.length];
465
466 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
467
468 final Key key = AES.newSecretKeySpec(keyBytes);
469
470 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
471 c.init(Cipher.DECRYPT_MODE, key, iv);
472 c.updateAAD(aad);
473
474
475 int len = c.update(input, 0, input.length, output, 0);
476 assertEquals(len, 0);
477 len += c.doFinal(input, input.length, 0, output, 0);
478 assertEquals(plainBytes.length, len);
479
480 assertArrayEquals(plainBytes, output);
481 }
482 }
483
484 @Test
485 public void testGcmTamperedData() throws Exception {
486
487 final Random r = new Random();
488 final int textLength = r.nextInt(1024*1024);
489 final int ivLength = r.nextInt(59) + 1;
490 final int keyLength = 16;
491 final int tagLength = 128;
492 final int aadLength = r.nextInt(128);
493
494 final byte[] keyBytes = new byte[keyLength];
495 final byte[] plainBytes = new byte[textLength];
496 final byte[] ivBytes = new byte[ivLength];
497 final byte[] aadBytes = new byte[aadLength];
498
499 r.nextBytes(keyBytes);
500 r.nextBytes(plainBytes);
501 r.nextBytes(ivBytes);
502 r.nextBytes(aadBytes);
503
504 final byte[] encOutput = new byte[plainBytes.length + (tagLength >> 3)];
505 final byte[] decOutput = new byte[plainBytes.length];
506
507 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
508 final Key key = AES.newSecretKeySpec(keyBytes);
509
510 final GCMParameterSpec iv = new GCMParameterSpec(tagLength, ivBytes);
511 c.init(Cipher.ENCRYPT_MODE, key, iv);
512 c.updateAAD(aadBytes);
513 c.doFinal(plainBytes, 0, plainBytes.length, encOutput, 0);
514 }
515
516
517 encOutput[0] = (byte)(encOutput[0] + 1);
518
519 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
520 final Key key = AES.newSecretKeySpec(keyBytes);
521
522 final GCMParameterSpec iv = new GCMParameterSpec(tagLength, ivBytes);
523 c.init(Cipher.DECRYPT_MODE, key, iv);
524 c.updateAAD(aadBytes);
525 final Exception ex = assertThrows(AEADBadTagException.class, () -> c.doFinal(encOutput, 0, encOutput.length, decOutput, 0));
526 assertEquals(ex.getMessage(), "Tag mismatch!");
527 }
528
529 }
530
531 @Test
532 public void testGMac() throws Exception {
533
534
535
536 final Random r = new Random();
537 final byte[] keyBytes = new byte[32];
538 final byte[] input = {};
539 final byte[] ivBytes = new byte[16];
540
541 final byte[] tag_orig = new byte[16];
542 final byte[] tag = new byte[16];
543
544
545 final byte[] aad = new byte[r.nextInt() % 1000 + 1000 ];
546
547 r.nextBytes(keyBytes);
548 r.nextBytes(input);
549 r.nextBytes(ivBytes);
550 r.nextBytes(aad);
551
552 {
553 final Cipher c = Cipher.getInstance(transformation);
554 final Key key = AES.newSecretKeySpec(keyBytes);
555 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
556 c.init(Cipher.ENCRYPT_MODE, key, iv);
557 c.updateAAD(aad);
558 c.doFinal(input, 0, input.length, tag_orig, 0);
559 }
560
561 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
562 final Key key = AES.newSecretKeySpec(keyBytes);
563 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
564 c.init(Cipher.ENCRYPT_MODE, key, iv);
565 c.updateAAD(aad);
566 c.doFinal(input, 0, input.length, tag, 0);
567 }
568
569
570 assertArrayEquals(tag_orig, tag);
571
572
573
574 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
575 final Key key = AES.newSecretKeySpec(keyBytes);
576 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
577 c.init(Cipher.DECRYPT_MODE, key, iv);
578 c.updateAAD(aad);
579 c.doFinal(tag, 0, tag.length, input, 0);
580 }
581 }
582
583 @Test
584
585 public void testGMacTamperedData() throws Exception {
586 final Random r = new Random();
587 final byte[] keyBytes = new byte[32];
588 final byte[] input = {};
589 final byte[] ivBytes = new byte[16];
590
591 final byte[] tag = new byte[16];
592
593 final byte[] aad = new byte[r.nextInt() % 1000 + 1000 ];
594
595 r.nextBytes(keyBytes);
596 r.nextBytes(input);
597 r.nextBytes(ivBytes);
598 r.nextBytes(aad);
599
600 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
601 final Key key = AES.newSecretKeySpec(keyBytes);
602 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
603 c.init(Cipher.ENCRYPT_MODE, key, iv);
604 c.updateAAD(aad);
605 c.doFinal(input, 0, input.length, tag, 0);
606 }
607
608
609 try (final CryptoCipher c = Utils.getCipherInstance(transformation, props)) {
610 final Key key = AES.newSecretKeySpec(keyBytes);
611 final GCMParameterSpec iv = new GCMParameterSpec(128, ivBytes);
612 c.init(Cipher.DECRYPT_MODE, key, iv);
613
614
615 aad[0] = (byte) (aad[0] + 1);
616 c.updateAAD(aad);
617
618 final Exception ex = assertThrows(AEADBadTagException.class, () -> c.doFinal(tag, 0, tag.length, input, 0));
619 assertEquals(ex.getMessage(), "Tag mismatch!");
620 }
621
622 }
623 }