· 6 years ago · Mar 23, 2019, 01:28 AM
1import javax.crypto.*;
2import javax.crypto.spec.GCMParameterSpec;
3import java.nio.ByteBuffer;
4import java.security.SecureRandom;
5import java.util.Arrays;
6
7public class AESGCMUpdateAAD2 {
8
9 // AES-GCM parameters
10 public static final int AES_KEY_SIZE = 128; // in bits
11 public static final int GCM_NONCE_LENGTH = 12; // in bytes
12 public static final int GCM_TAG_LENGTH = 16; // in bytes
13
14 public static void main(String[] args) throws Exception {
15 int testNum = 0; // pass
16
17 if (args.length > 0) {
18 testNum = Integer.parseInt(args[0]);
19 if (testNum <0 || testNum > 3) {
20 System.out.println("Usage: java AESGCMUpdateAAD2 [X]");
21 System.out.println("X can be 0, 1, 2, 3");
22 System.exit(1);
23 }
24 }
25 byte[] input = "Hello AES-GCM World!".getBytes();
26
27 // Initialise random and generate key
28 SecureRandom random = SecureRandom.getInstanceStrong();
29 KeyGenerator keyGen = KeyGenerator.getInstance("AES");
30 keyGen.init(AES_KEY_SIZE, random);
31 SecretKey key = keyGen.generateKey();
32
33 // Encrypt
34 Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding", "SunJCE");
35 final byte[] nonce = new byte[GCM_NONCE_LENGTH];
36 random.nextBytes(nonce);
37 GCMParameterSpec spec = new GCMParameterSpec(GCM_TAG_LENGTH * 8, nonce);
38 cipher.init(Cipher.ENCRYPT_MODE, key, spec);
39
40 byte[] aad = "Whatever I like".getBytes();;
41 cipher.updateAAD(aad);
42
43 byte[] cipherText = cipher.doFinal(input);
44
45 // Decrypt; nonce is shared implicitly
46 cipher.init(Cipher.DECRYPT_MODE, key, spec);
47
48 // EXPECTED: Uncommenting this will cause an AEADBadTagException when decrypting
49 // because AAD value is altered
50 if (testNum == 1) aad[1]++;
51
52 cipher.updateAAD(aad);
53
54 // EXPECTED: Uncommenting this will cause an AEADBadTagException when decrypting
55 // because the encrypted data has been altered
56 if (testNum == 2) cipherText[10]++;
57
58 // EXPECTED: Uncommenting this will cause an AEADBadTagException when decrypting
59 // because the tag has been altered
60 if (testNum == 3) cipherText[cipherText.length - 2]++;
61
62 try {
63 byte[] plainText = cipher.doFinal(cipherText);
64 if (testNum != 0) {
65 System.out.println("Test Failed: expected AEADBadTagException not thrown");
66 } else {
67 // check if the decryption result matches
68 if (Arrays.equals(input, plainText)) {
69 System.out.println("Test Passed: match!");
70 } else {
71 System.out.println("Test Failed: result mismatch!");
72 System.out.println(new String(plainText));
73 }
74 }
75 } catch(AEADBadTagException ex) {
76 if (testNum == 0) {
77 System.out.println("Test Failed: unexpected ex " + ex);
78 ex.printStackTrace();
79 } else {
80 System.out.println("Test Passed: expected ex " + ex);
81 }
82 }
83 }
84}