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 static java.security.spec.MGF1ParameterSpec.SHA256;
20 import static javax.crypto.spec.PSource.PSpecified.DEFAULT;
21 import static org.forgerock.json.jose.jwe.JweAlgorithm.RSA_OAEP_256;
22 import static org.forgerock.json.jose.jwe.JweAlgorithmType.RSA;
23 import static org.forgerock.util.Reject.checkNotNull;
24
25 import java.security.GeneralSecurityException;
26 import java.security.Key;
27 import java.security.interfaces.RSAPublicKey;
28 import java.security.spec.AlgorithmParameterSpec;
29
30 import javax.crypto.Cipher;
31 import javax.crypto.spec.OAEPParameterSpec;
32
33 import org.forgerock.json.jose.exceptions.JweDecryptionException;
34 import org.forgerock.json.jose.exceptions.JweEncryptionException;
35 import org.forgerock.json.jose.jwe.EncryptionMethod;
36 import org.forgerock.json.jose.jwe.JweAlgorithm;
37 import org.forgerock.json.jose.jwe.JweEncryption;
38 import org.forgerock.util.Reject;
39
40
41
42
43
44
45 public final class RSAEncryptionHandler implements EncryptionHandler {
46 private static final OAEPParameterSpec RSA_OAEP_256_PARAMS = new OAEPParameterSpec("SHA-256", "MGF1", SHA256,
47 DEFAULT);
48 private final EncryptionMethod encryptionMethod;
49 private final ContentEncryptionHandler contentEncryptionHandler;
50 private final JweAlgorithm jweAlgorithm;
51 private final AlgorithmParameterSpec parameterSpec;
52
53
54
55
56
57
58
59 public RSAEncryptionHandler(EncryptionMethod encryptionMethod, final JweAlgorithm jweAlgorithm) {
60 this.encryptionMethod = checkNotNull(encryptionMethod, "EncryptionMethod must not be null");
61 this.jweAlgorithm = checkNotNull(jweAlgorithm, "JweAlgorithm must not be null");
62 Reject.ifFalse(jweAlgorithm.getAlgorithmType() == RSA, "JweAlgorithm type must be RSA");
63 this.contentEncryptionHandler = ContentEncryptionHandler.getInstance(encryptionMethod);
64
65
66 this.parameterSpec = jweAlgorithm == RSA_OAEP_256 ? RSA_OAEP_256_PARAMS : null;
67 }
68
69
70
71
72
73
74
75
76
77
78 @Override
79 public Key getContentEncryptionKey() {
80 return contentEncryptionHandler.generateEncryptionKey();
81 }
82
83
84
85
86
87
88
89
90
91
92
93
94 @Override
95 public byte[] generateJWEEncryptedKey(Key key, Key contentEncryptionKey) {
96 return encryptKey((RSAPublicKey) key, contentEncryptionKey);
97 }
98
99
100
101
102
103
104
105
106
107 @Override
108 public byte[] generateInitialisationVector() {
109 return contentEncryptionHandler.generateInitialisationVector();
110 }
111
112
113
114
115 @Override
116 public JweEncryption encryptPlaintext(Key contentEncryptionKey, byte[] initialisationVector, byte[] plaintext,
117 byte[] additionalAuthenticatedData) {
118
119 return contentEncryptionHandler.encrypt(contentEncryptionKey, initialisationVector, plaintext,
120 additionalAuthenticatedData);
121 }
122
123
124
125
126
127
128
129
130
131
132
133 @Override
134 public Key decryptContentEncryptionKey(Key key, byte[] encryptedContentEncryptionKey) {
135 try {
136 final Cipher cipher = Cipher.getInstance(jweAlgorithm.getAlgorithm());
137 cipher.init(Cipher.UNWRAP_MODE, key, parameterSpec);
138 return cipher.unwrap(encryptedContentEncryptionKey, encryptionMethod.getEncryptionAlgorithm(),
139 Cipher.SECRET_KEY);
140 } catch (GeneralSecurityException e) {
141 throw new JweDecryptionException();
142 }
143 }
144
145
146
147
148 @Override
149 public byte[] decryptCiphertext(Key contentEncryptionKey, byte[] initialisationVector, byte[] ciphertext,
150 byte[] authenticationTag, byte[] additionalAuthenticatedData) {
151 return contentEncryptionHandler.decrypt(contentEncryptionKey, initialisationVector,
152 new JweEncryption(ciphertext, authenticationTag), additionalAuthenticatedData);
153 }
154
155 private byte[] encryptKey(final RSAPublicKey keyEncryptionKey, final Key contentKey) {
156 try {
157 final Cipher cipher = Cipher.getInstance(jweAlgorithm.getAlgorithm());
158 cipher.init(Cipher.WRAP_MODE, keyEncryptionKey, parameterSpec);
159 return cipher.wrap(contentKey);
160 } catch (GeneralSecurityException e) {
161 throw new JweEncryptionException(e);
162 }
163 }
164 }