1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.forgerock.json.jose.jwe.handlers.encryption;
18
19 import java.security.GeneralSecurityException;
20 import java.security.Key;
21 import java.security.NoSuchAlgorithmException;
22 import java.util.Arrays;
23 import java.util.logging.Level;
24 import java.util.logging.Logger;
25
26 import javax.crypto.Cipher;
27 import javax.crypto.KeyGenerator;
28 import javax.crypto.spec.GCMParameterSpec;
29
30 import org.forgerock.json.jose.exceptions.JweDecryptionException;
31 import org.forgerock.json.jose.exceptions.JweEncryptionException;
32 import org.forgerock.json.jose.jwe.EncryptionMethod;
33 import org.forgerock.json.jose.jwe.JweEncryption;
34
35
36
37
38
39
40
41 final class AESGCMContentEncryptionHandler extends ContentEncryptionHandler {
42 private static final Logger LOGGER = Logger.getLogger(AESGCMContentEncryptionHandler.class.getName());
43 private static final int TAG_LENGTH = 128;
44 private static final int IV_LENGTH = 96 / 8;
45
46 private final EncryptionMethod encryptionMethod;
47
48 AESGCMContentEncryptionHandler(final EncryptionMethod encryptionMethod) {
49 this.encryptionMethod = encryptionMethod;
50 }
51
52 @Override
53 JweEncryption encrypt(final Key key, final byte[] iv, final byte[] plainText, final byte[] additionalData) {
54 try {
55 final Cipher cipher = Cipher.getInstance(encryptionMethod.getTransformation());
56 cipher.init(Cipher.ENCRYPT_MODE, key, new GCMParameterSpec(TAG_LENGTH, iv));
57 cipher.updateAAD(additionalData);
58 final byte[] cipherText = cipher.doFinal(plainText);
59
60 final int tagStart = cipherText.length - TAG_LENGTH / 8;
61 return new JweEncryption(Arrays.copyOfRange(cipherText, 0, tagStart),
62 Arrays.copyOfRange(cipherText, tagStart, cipherText.length));
63 } catch (GeneralSecurityException ex) {
64 throw new JweEncryptionException(ex);
65 }
66 }
67
68 @Override
69 byte[] decrypt(final Key key, final byte[] iv, final JweEncryption cipherText, final byte[] additionalData) {
70 try {
71 final Cipher cipher = Cipher.getInstance(encryptionMethod.getTransformation());
72 cipher.init(Cipher.DECRYPT_MODE, key, new GCMParameterSpec(TAG_LENGTH, iv));
73 cipher.updateAAD(additionalData);
74 cipher.update(cipherText.getCiphertext());
75 return cipher.doFinal(cipherText.getAuthenticationTag());
76 } catch (GeneralSecurityException ex) {
77 if (LOGGER.isLoggable(Level.FINE)) {
78 LOGGER.log(Level.FINE, "Decryption failed: " + ex, ex);
79 }
80 throw new JweDecryptionException();
81 }
82 }
83
84 @Override
85 Key generateEncryptionKey() {
86 try {
87 final KeyGenerator encKeyGenerator = KeyGenerator.getInstance(encryptionMethod.getEncryptionAlgorithm());
88 encKeyGenerator.init(encryptionMethod.getKeySize());
89 return encKeyGenerator.generateKey();
90 } catch (NoSuchAlgorithmException e) {
91 throw new JweEncryptionException("Unsupported Encryption Algorithm, "
92 + encryptionMethod.getEncryptionAlgorithm(), e);
93 }
94 }
95
96 @Override
97 int getIVByteLength() {
98 return IV_LENGTH;
99 }
100 }