001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2026, Connect2id Ltd. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.jose.crypto; 019 020 021import java.util.Collections; 022import java.util.Set; 023import javax.crypto.SecretKey; 024import javax.crypto.spec.SecretKeySpec; 025 026import com.nimbusds.jose.*; 027import com.nimbusds.jose.crypto.impl.*; 028import com.nimbusds.jose.crypto.opts.OptionUtils; 029import com.nimbusds.jose.jwk.OctetSequenceKey; 030import com.nimbusds.jose.util.Base64URL; 031import net.jcip.annotations.ThreadSafe; 032 033 034/** 035 * Direct decrypter of {@link com.nimbusds.jose.JWEObject JWE objects} with a 036 * shared symmetric key. 037 * 038 * <p>See RFC 7518 039 * <a href="https://tools.ietf.org/html/rfc7518#section-4.5">section 4.5</a> 040 * for more information.</p> 041 * 042 * <p>This class is thread-safe. 043 * 044 * <p>Supports the following key management algorithms: 045 * 046 * <ul> 047 * <li>{@link com.nimbusds.jose.JWEAlgorithm#DIR} 048 * </ul> 049 * 050 * <p>Supports the following content encryption algorithms: 051 * 052 * <ul> 053 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} (requires 256 bit key) 054 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} (requires 384 bit key) 055 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} (requires 512 bit key) 056 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} (requires 128 bit key) 057 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} (requires 192 bit key) 058 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} (requires 256 bit key) 059 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} (requires 256 bit key) 060 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} (requires 512 bit key) 061 * <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} (requires 256 bit key) 062 * </ul> 063 * 064 * <p>Also supports a promiscuous mode to decrypt any JWE by passing the 065 * content encryption key (CEK) directly. The that mode the JWE algorithm 066 * checks for ("alg":"dir") and encrypted key not being present will be 067 * skipped. 068 * 069 * @author Vladimir Dzhuvinov 070 * @author Egor Puzanov 071 * @version 2026-09-16 072 */ 073@ThreadSafe 074public class DirectDecrypter extends DirectCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 075 076 077 /** 078 * If set skips the checks for alg "dir" and encrypted key not present. 079 */ 080 private final boolean promiscuousMode; 081 082 083 /** 084 * The critical header policy. 085 */ 086 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 087 088 089 /** 090 * The configured options, empty set if none. 091 */ 092 private final Set<JWEDecrypterOption> opts; 093 094 095 /** 096 * Creates a new direct decrypter. 097 * 098 * @param key The symmetric key. Its algorithm should be "AES". Must be 099 * 128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32 100 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) long. 101 * Must not be {@code null}. 102 * 103 * @throws KeyLengthException If the symmetric key length is not 104 * compatible. 105 */ 106 public DirectDecrypter(final SecretKey key) 107 throws KeyLengthException { 108 109 this(key, false); 110 } 111 112 113 /** 114 * Creates a new direct decrypter with the option to set it in 115 * promiscuous mode. 116 * 117 * @param key The symmetric key. Its algorithm should be 118 * "AES". Must be 128 bits (16 bytes), 192 bits 119 * (24 bytes), 256 bits (32 bytes), 384 bits (48 120 * bytes) or 512 bits (64 bytes) long. Must not 121 * be {@code null}. 122 * @param promiscuousMode If {@code true} set the decrypter in 123 * promiscuous mode to permit decryption of any 124 * JWE with the supplied symmetric key. In that 125 * mode the JWE algorithm checks for 126 * ("alg":"dir") and encrypted key not being 127 * present will be skipped. 128 * 129 * @throws KeyLengthException If the symmetric key length is not 130 * compatible. 131 */ 132 public DirectDecrypter(final SecretKey key, final boolean promiscuousMode) 133 throws KeyLengthException { 134 135 this(key, null, promiscuousMode, Collections.<JWEDecrypterOption>emptySet()); 136 } 137 138 139 /** 140 * Creates a new direct decrypter. 141 * 142 * @param keyBytes The symmetric key, as a byte array. Must be 128 bits 143 * (16 bytes), 192 bits (24 bytes), 256 bits (32 144 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) 145 * long. Must not be {@code null}. 146 * 147 * @throws KeyLengthException If the symmetric key length is not 148 * compatible. 149 */ 150 public DirectDecrypter(final byte[] keyBytes) 151 throws KeyLengthException { 152 153 this(new SecretKeySpec(keyBytes, "AES"), false); 154 } 155 156 157 /** 158 * Creates a new direct decrypter. 159 * 160 * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16 161 * bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384 162 * bits (48 bytes) or 512 bits (64 bytes) long. Must not 163 * be {@code null}. 164 * 165 * @throws KeyLengthException If the symmetric key length is not 166 * compatible. 167 */ 168 public DirectDecrypter(final OctetSequenceKey octJWK) 169 throws KeyLengthException { 170 171 this(octJWK.toSecretKey("AES")); 172 } 173 174 175 /** 176 * Creates a new direct decrypter with the option to set it in 177 * promiscuous mode. 178 * 179 * @param key The symmetric key. Its algorithm should be 180 * "AES". Must be 128 bits (16 bytes), 192 bits 181 * (24 bytes), 256 bits (32 bytes), 384 bits (48 182 * bytes) or 512 bits (64 bytes) long. Must not 183 * be {@code null}. 184 * @param defCritHeaders The names of the critical header parameters 185 * that are deferred to the application for 186 * processing, empty set or {@code null} if none. 187 * 188 * @throws KeyLengthException If the symmetric key length is not 189 * compatible. 190 */ 191 public DirectDecrypter(final SecretKey key, final Set<String> defCritHeaders) 192 throws KeyLengthException { 193 194 this(key, defCritHeaders, false); 195 } 196 197 198 /** 199 * Creates a new direct decrypter. 200 * 201 * @param key The symmetric key. Its algorithm should be 202 * "AES". Must be 128 bits (16 bytes), 192 bits 203 * (24 bytes), 256 bits (32 bytes), 384 bits (48 204 * bytes) or 512 bits (64 bytes) long. Must not 205 * be {@code null}. 206 * @param defCritHeaders The names of the critical header parameters 207 * that are deferred to the application for 208 * processing, empty set or {@code null} if none. 209 *@param promiscuousMode If {@code true} set the decrypter in 210 * promiscuous mode to permit decryption of any 211 * JWE with the supplied symmetric key. In that 212 * mode the JWE algorithm checks for 213 * ("alg":"dir") and encrypted key not being 214 * present will be skipped. 215 * 216 * @throws KeyLengthException If the symmetric key length is not 217 * compatible. 218 */ 219 public DirectDecrypter(final SecretKey key, 220 final Set<String> defCritHeaders, 221 final boolean promiscuousMode) 222 throws KeyLengthException { 223 224 this(key, defCritHeaders, promiscuousMode, Collections.<JWEDecrypterOption>emptySet()); 225 } 226 227 228 /** 229 * Creates a new direct decrypter. 230 * 231 * @param key The symmetric key. Its algorithm should be 232 * "AES". Must be 128 bits (16 bytes), 192 bits 233 * (24 bytes), 256 bits (32 bytes), 384 bits (48 234 * bytes) or 512 bits (64 bytes) long. Must not 235 * be {@code null}. 236 * @param defCritHeaders The names of the critical header parameters 237 * that are deferred to the application for 238 * processing, empty set or {@code null} if none. 239 * @param promiscuousMode If {@code true} set the decrypter in 240 * promiscuous mode to permit decryption of any 241 * JWE with the supplied symmetric key. The that 242 * mode the JWE algorithm checks for 243 * ("alg":"dir") and encrypted key not being 244 * present will be skipped. 245 * @param opts The decryption options, empty or {@code null} 246 * if none. 247 * 248 * @throws KeyLengthException If the symmetric key length is not 249 * compatible. 250 */ 251 public DirectDecrypter(final SecretKey key, 252 final Set<String> defCritHeaders, 253 final boolean promiscuousMode, 254 final Set<JWEDecrypterOption> opts) 255 throws KeyLengthException { 256 257 super(key); 258 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 259 this.promiscuousMode = promiscuousMode; 260 this.opts = opts != null ? opts : Collections.<JWEDecrypterOption>emptySet(); 261 } 262 263 264 /** 265 * Creates a new direct decrypter. 266 * 267 * @param key The symmetric key. Its algorithm should be 268 * "AES". Must be 128 bits (16 bytes), 192 bits 269 * (24 bytes), 256 bits (32 bytes), 384 bits (48 270 * bytes) or 512 bits (64 bytes) long. Must not 271 * be {@code null}. 272 * @param defCritHeaders The names of the critical header parameters 273 * that are deferred to the application for 274 * processing, empty set or {@code null} if none. 275 * @param opts The decryption options, empty or {@code null} 276 * if none. 277 * 278 * @throws KeyLengthException If the symmetric key length is not 279 * compatible. 280 */ 281 public DirectDecrypter(final SecretKey key, 282 final Set<String> defCritHeaders, 283 final Set<JWEDecrypterOption> opts) 284 throws KeyLengthException { 285 286 this(key, defCritHeaders, false, opts); 287 } 288 289 290 /** 291 * Creates a new direct decrypter with the option to set it in 292 * promiscuous mode. 293 * 294 * @param key The symmetric key. Its algorithm should be 295 * "AES". Must be 128 bits (16 bytes), 192 bits 296 * (24 bytes), 256 bits (32 bytes), 384 bits (48 297 * bytes) or 512 bits (64 bytes) long. Must not 298 * be {@code null}. 299 * @param promiscuousMode If {@code true} set the decrypter in 300 * promiscuous mode to permit decryption of any 301 * JWE with the supplied symmetric key. In that 302 * mode the JWE algorithm checks for 303 * ("alg":"dir") and encrypted key not being 304 * present will be skipped. 305 * @param opts The decryption options, empty or {@code null} 306 * if none. 307 * 308 * @throws KeyLengthException If the symmetric key length is not 309 * compatible. 310 */ 311 public DirectDecrypter(final SecretKey key, 312 final boolean promiscuousMode, 313 final Set<JWEDecrypterOption> opts) 314 throws KeyLengthException { 315 316 this(key, null, promiscuousMode, opts); 317 } 318 319 320 /** 321 * Creates a new direct decrypter. 322 * 323 * @param keyBytes The symmetric key, as a byte array. Must be 128 bits 324 * (16 bytes), 192 bits (24 bytes), 256 bits (32 325 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) 326 * long. Must not be {@code null}. 327 * @param opts The decryption options, empty or {@code null} if 328 * none. 329 * 330 * @throws KeyLengthException If the symmetric key length is not 331 * compatible. 332 */ 333 public DirectDecrypter(final byte[] keyBytes, 334 final Set<JWEDecrypterOption> opts) 335 throws KeyLengthException { 336 337 this(new SecretKeySpec(keyBytes, "AES"), null, false, opts); 338 } 339 340 341 /** 342 * Creates a new direct decrypter. 343 * 344 * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16 345 * bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384 346 * bits (48 bytes) or 512 bits (64 bytes) long. Must not 347 * be {@code null}. 348 * @param opts The decryption options, empty or {@code null} if none. 349 * 350 * @throws KeyLengthException If the symmetric key length is not 351 * compatible. 352 */ 353 public DirectDecrypter(final OctetSequenceKey octJWK, 354 final Set<JWEDecrypterOption> opts) 355 throws KeyLengthException { 356 357 this(octJWK.toSecretKey("AES"), null, false, opts); 358 } 359 360 361 /** 362 * Creates a new direct decrypter. 363 * 364 * @param octJWK The symmetric key, as a JWK. Must be 128 bits 365 * (16 bytes), 192 bits (24 bytes), 256 bits (32 366 * bytes), 384 bits (48 bytes) or 512 bits (64 367 * bytes) long. Must not be {@code null}. 368 * @param defCritHeaders The names of the critical header parameters 369 * that are deferred to the application for 370 * processing, empty set or {@code null} if none. 371 * @param opts The decryption options, empty or {@code null} 372 * if none. 373 * 374 * @throws KeyLengthException If the symmetric key length is not 375 * compatible. 376 */ 377 public DirectDecrypter(final OctetSequenceKey octJWK, 378 final Set<String> defCritHeaders, 379 final Set<JWEDecrypterOption> opts) 380 throws KeyLengthException { 381 382 this(octJWK.toSecretKey("AES"), defCritHeaders, false, opts); 383 } 384 385 386 @Override 387 public Set<String> getProcessedCriticalHeaderParams() { 388 389 return critPolicy.getProcessedCriticalHeaderParams(); 390 } 391 392 393 @Override 394 public Set<String> getDeferredCriticalHeaderParams() { 395 396 return critPolicy.getDeferredCriticalHeaderParams(); 397 } 398 399 400 /** 401 * Decrypts the specified cipher text of a {@link JWEObject JWE Object}. 402 * 403 * @param header The JSON Web Encryption (JWE) header. Must 404 * specify a supported JWE algorithm and method. 405 * Must not be {@code null}. 406 * @param encryptedKey The encrypted key, {@code null} if not required 407 * by the JWE algorithm. 408 * @param iv The initialisation vector, {@code null} if not 409 * required by the JWE algorithm. 410 * @param cipherText The cipher text to decrypt. Must not be 411 * {@code null}. 412 * @param authTag The authentication tag, {@code null} if not 413 * required. 414 * 415 * @return The clear text. 416 * 417 * @throws JOSEException If the JWE algorithm or method is not 418 * supported, if a critical header parameter is 419 * not supported or marked for deferral to the 420 * application, or if decryption failed for some 421 * other reason. 422 */ 423 @Deprecated 424 public byte[] decrypt(final JWEHeader header, 425 final Base64URL encryptedKey, 426 final Base64URL iv, 427 final Base64URL cipherText, 428 final Base64URL authTag) 429 throws JOSEException { 430 431 return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header)); 432 } 433 434 435 @Override 436 public byte[] decrypt(final JWEHeader header, 437 final Base64URL encryptedKey, 438 final Base64URL iv, 439 final Base64URL cipherText, 440 final Base64URL authTag, 441 final byte[] aad) 442 throws JOSEException { 443 444 // Validate required JWE parts 445 if (! promiscuousMode) { 446 447 JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header); 448 449 if (!alg.equals(JWEAlgorithm.DIR)) { 450 throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); 451 } 452 453 if (encryptedKey != null) { 454 throw new JOSEException("Unexpected present JWE encrypted key"); 455 } 456 } 457 458 if (iv == null) { 459 throw new JOSEException("Unexpected present JWE initialization vector (IV)"); 460 } 461 462 if (authTag == null) { 463 throw new JOSEException("Missing JWE authentication tag"); 464 } 465 466 critPolicy.ensureHeaderPasses(header); 467 468 int maxDecompressedLength = OptionUtils.resolveMaxDecompressedPlainTextLength(opts); 469 470 return ContentCryptoProvider.decrypt(header, aad, null, iv, cipherText, authTag, getKey(), getJCAContext(), maxDecompressedLength); 471 } 472}