001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2016, 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.Set; 022import javax.crypto.SecretKey; 023import javax.crypto.spec.SecretKeySpec; 024 025import com.nimbusds.jose.*; 026import com.nimbusds.jose.crypto.impl.*; 027import com.nimbusds.jose.jwk.OctetSequenceKey; 028import com.nimbusds.jose.util.Base64URL; 029import net.jcip.annotations.ThreadSafe; 030 031 032/** 033 * Direct decrypter of {@link com.nimbusds.jose.JWEObject JWE objects} with a 034 * shared symmetric key. 035 * 036 * <p>See RFC 7518 037 * <a href="https://tools.ietf.org/html/rfc7518#section-4.5">section 4.5</a> 038 * for more information.</p> 039 * 040 * <p>This class is thread-safe. 041 * 042 * <p>Supports the following key management algorithms: 043 * 044 * <ul> 045 * <li>{@link com.nimbusds.jose.JWEAlgorithm#DIR} 046 * </ul> 047 * 048 * <p>Supports the following content encryption algorithms: 049 * 050 * <ul> 051 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} (requires 256 bit key) 052 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} (requires 384 bit key) 053 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} (requires 512 bit key) 054 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} (requires 128 bit key) 055 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} (requires 192 bit key) 056 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} (requires 256 bit key) 057 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} (requires 256 bit key) 058 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} (requires 512 bit key) 059 * <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} (requires 256 bit key) 060 * </ul> 061 * 062 * <p>Also supports a promiscuous mode to decrypt any JWE by passing the 063 * content encryption key (CEK) directly. The that mode the JWE algorithm 064 * checks for ("alg":"dir") and encrypted key not being present will be 065 * skipped. 066 * 067 * @author Vladimir Dzhuvinov 068 * @author Egor Puzanov 069 * @version 2023-09-10 070 */ 071@ThreadSafe 072public class DirectDecrypter extends DirectCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 073 074 075 /** 076 * If set skips the checks for alg "dir" and encrypted key not present. 077 */ 078 private final boolean promiscuousMode; 079 080 081 /** 082 * The critical header policy. 083 */ 084 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 085 086 087 /** 088 * Creates a new direct decrypter. 089 * 090 * @param key The symmetric key. Its algorithm should be "AES". Must be 091 * 128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32 092 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) long. 093 * Must not be {@code null}. 094 * 095 * @throws KeyLengthException If the symmetric key length is not 096 * compatible. 097 */ 098 public DirectDecrypter(final SecretKey key) 099 throws KeyLengthException { 100 101 this(key, false); 102 } 103 104 105 /** 106 * Creates a new direct decrypter with the option to set it in 107 * promiscuous mode. 108 * 109 * @param key The symmetric key. Its algorithm should be 110 * "AES". Must be 128 bits (16 bytes), 192 bits 111 * (24 bytes), 256 bits (32 bytes), 384 bits (48 112 * bytes) or 512 bits (64 bytes) long. Must not 113 * be {@code null}. 114 * @param promiscuousMode If {@code true} set the decrypter in 115 * promiscuous mode to permit decryption of any 116 * JWE with the supplied symmetric key. The that 117 * mode the JWE algorithm checks for 118 * ("alg":"dir") and encrypted key not being 119 * present will be skipped. 120 * 121 * @throws KeyLengthException If the symmetric key length is not 122 * compatible. 123 */ 124 public DirectDecrypter(final SecretKey key, final boolean promiscuousMode) 125 throws KeyLengthException { 126 127 super(key); 128 129 this.promiscuousMode = promiscuousMode; 130 } 131 132 133 /** 134 * Creates a new direct decrypter. 135 * 136 * @param keyBytes The symmetric key, as a byte array. Must be 128 bits 137 * (16 bytes), 192 bits (24 bytes), 256 bits (32 138 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) 139 * long. Must not be {@code null}. 140 * 141 * @throws KeyLengthException If the symmetric key length is not 142 * compatible. 143 */ 144 public DirectDecrypter(final byte[] keyBytes) 145 throws KeyLengthException { 146 147 this(new SecretKeySpec(keyBytes, "AES"), false); 148 } 149 150 151 /** 152 * Creates a new direct decrypter. 153 * 154 * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16 155 * bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384 156 * bits (48 bytes) or 512 bits (64 bytes) long. Must not 157 * be {@code null}. 158 * 159 * @throws KeyLengthException If the symmetric key length is not 160 * compatible. 161 */ 162 public DirectDecrypter(final OctetSequenceKey octJWK) 163 throws KeyLengthException { 164 165 this(octJWK.toSecretKey("AES")); 166 } 167 168 169 /** 170 * Creates a new direct decrypter with the option to set it in 171 * promiscuous mode. 172 * 173 * @param key The symmetric key. Its algorithm should be 174 * "AES". Must be 128 bits (16 bytes), 192 bits 175 * (24 bytes), 256 bits (32 bytes), 384 bits (48 176 * bytes) or 512 bits (64 bytes) long. Must not 177 * be {@code null}. 178 * @param defCritHeaders The names of the critical header parameters 179 * that are deferred to the application for 180 * processing, empty set or {@code null} if none. 181 * 182 * @throws KeyLengthException If the symmetric key length is not 183 * compatible. 184 */ 185 public DirectDecrypter(final SecretKey key, final Set<String> defCritHeaders) 186 throws KeyLengthException { 187 188 this(key, defCritHeaders, false); 189 } 190 191 192 /** 193 * Creates a new direct decrypter. 194 * 195 * @param key The symmetric key. Its algorithm should be 196 * "AES". Must be 128 bits (16 bytes), 192 bits 197 * (24 bytes), 256 bits (32 bytes), 384 bits (48 198 * bytes) or 512 bits (64 bytes) long. Must not 199 * be {@code null}. 200 * @param defCritHeaders The names of the critical header parameters 201 * that are deferred to the application for 202 * processing, empty set or {@code null} if none. 203 *@param promiscuousMode If {@code true} set the decrypter in 204 * promiscuous mode to permit decryption of any 205 * JWE with the supplied symmetric key. The that 206 * mode the JWE algorithm checks for 207 * ("alg":"dir") and encrypted key not being 208 * present will be skipped. 209 * 210 * @throws KeyLengthException If the symmetric key length is not 211 * compatible. 212 */ 213 public DirectDecrypter(final SecretKey key, 214 final Set<String> defCritHeaders, 215 final boolean promiscuousMode) 216 throws KeyLengthException { 217 218 super(key); 219 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 220 this.promiscuousMode = promiscuousMode; 221 } 222 223 224 @Override 225 public Set<String> getProcessedCriticalHeaderParams() { 226 227 return critPolicy.getProcessedCriticalHeaderParams(); 228 } 229 230 231 @Override 232 public Set<String> getDeferredCriticalHeaderParams() { 233 234 return critPolicy.getProcessedCriticalHeaderParams(); 235 } 236 237 238 /** 239 * Decrypts the specified cipher text of a {@link JWEObject JWE Object}. 240 * 241 * @param header The JSON Web Encryption (JWE) header. Must 242 * specify a supported JWE algorithm and method. 243 * Must not be {@code null}. 244 * @param encryptedKey The encrypted key, {@code null} if not required 245 * by the JWE algorithm. 246 * @param iv The initialisation vector, {@code null} if not 247 * required by the JWE algorithm. 248 * @param cipherText The cipher text to decrypt. Must not be 249 * {@code null}. 250 * @param authTag The authentication tag, {@code null} if not 251 * required. 252 * 253 * @return The clear text. 254 * 255 * @throws JOSEException If the JWE algorithm or method is not 256 * supported, if a critical header parameter is 257 * not supported or marked for deferral to the 258 * application, or if decryption failed for some 259 * other reason. 260 */ 261 @Deprecated 262 public byte[] decrypt(final JWEHeader header, 263 final Base64URL encryptedKey, 264 final Base64URL iv, 265 final Base64URL cipherText, 266 final Base64URL authTag) 267 throws JOSEException { 268 269 return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header)); 270 } 271 272 273 @Override 274 public byte[] decrypt(final JWEHeader header, 275 final Base64URL encryptedKey, 276 final Base64URL iv, 277 final Base64URL cipherText, 278 final Base64URL authTag, 279 final byte[] aad) 280 throws JOSEException { 281 282 // Validate required JWE parts 283 if (! promiscuousMode) { 284 285 JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header); 286 287 if (!alg.equals(JWEAlgorithm.DIR)) { 288 throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); 289 } 290 291 if (encryptedKey != null) { 292 throw new JOSEException("Unexpected present JWE encrypted key"); 293 } 294 } 295 296 if (iv == null) { 297 throw new JOSEException("Unexpected present JWE initialization vector (IV)"); 298 } 299 300 if (authTag == null) { 301 throw new JOSEException("Missing JWE authentication tag"); 302 } 303 304 critPolicy.ensureHeaderPasses(header); 305 306 return ContentCryptoProvider.decrypt(header, aad, null, iv, cipherText, authTag, getKey(), getJCAContext()); 307 } 308}