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; 022 023import javax.crypto.SecretKey; 024import javax.crypto.spec.SecretKeySpec; 025 026import com.nimbusds.jose.crypto.impl.*; 027import net.jcip.annotations.ThreadSafe; 028 029import com.nimbusds.jose.*; 030import com.nimbusds.jose.jwk.OctetSequenceKey; 031import com.nimbusds.jose.util.Base64URL; 032 033 034/** 035 * AES and AES GCM key wrap decrypter of {@link com.nimbusds.jose.JWEObject JWE 036 * objects}. Expects an AES key. 037 * 038 * <p>Unwraps the encrypted Content Encryption Key (CEK) with the specified AES 039 * key, and then uses the CEK along with the IV and authentication tag to 040 * decrypt the cipher text. See RFC 7518, sections 041 * <a href="https://tools.ietf.org/html/rfc7518#section-4.4">4.4</a> and 042 * <a href="https://tools.ietf.org/html/rfc7518#section-4.7">4.7</a> for more 043 * information. 044 * 045 * <p>This class is thread-safe. 046 * 047 * <p>Supports the following key management algorithms: 048 * 049 * <ul> 050 * <li>{@link com.nimbusds.jose.JWEAlgorithm#A128KW} 051 * <li>{@link com.nimbusds.jose.JWEAlgorithm#A192KW} 052 * <li>{@link com.nimbusds.jose.JWEAlgorithm#A256KW} 053 * <li>{@link com.nimbusds.jose.JWEAlgorithm#A128GCMKW} 054 * <li>{@link com.nimbusds.jose.JWEAlgorithm#A192GCMKW} 055 * <li>{@link com.nimbusds.jose.JWEAlgorithm#A256GCMKW} 056 * </ul> 057 * 058 * <p>Supports the following content encryption algorithms: 059 * 060 * <ul> 061 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 062 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 063 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 064 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} 065 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} 066 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} 067 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} 068 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} 069 * <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} 070 * </ul> 071 * 072 * @author Melisa Halsband 073 * @author Vladimir Dzhuvinov 074 * @author Egor Puzanov 075 * @version 2023-09-10 076 */ 077@ThreadSafe 078public class AESDecrypter extends AESCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 079 080 081 /** 082 * The critical header policy. 083 */ 084 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 085 086 087 /** 088 * Creates a new AES decrypter. 089 * 090 * @param kek The Key Encrypting Key. Must be 128 bits (16 bytes), 192 091 * bits (24 bytes) or 256 bits (32 bytes). Must not be 092 * {@code null}. 093 * 094 * @throws KeyLengthException If the KEK length is invalid. 095 */ 096 public AESDecrypter(final SecretKey kek) 097 throws KeyLengthException { 098 099 this(kek, null); 100 } 101 102 103 /** 104 * Creates a new AES decrypter. 105 * 106 * @param keyBytes The Key Encrypting Key, as a byte array. Must be 128 107 * bits (16 bytes), 192 bits (24 bytes) or 256 bits (32 108 * bytes). Must not be {@code null}. 109 * 110 * @throws KeyLengthException If the KEK length is invalid. 111 */ 112 public AESDecrypter(final byte[] keyBytes) 113 throws KeyLengthException { 114 115 this(new SecretKeySpec(keyBytes, "AES")); 116 } 117 118 119 /** 120 * Creates a new AES decrypter. 121 * 122 * @param octJWK The Key Encryption Key, as a JWK. Must be 128 bits (16 123 * bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384 124 * bits (48 bytes) or 512 bits (64 bytes) long. Must not 125 * be {@code null}. 126 * 127 * @throws KeyLengthException If the KEK length is invalid. 128 */ 129 public AESDecrypter(final OctetSequenceKey octJWK) 130 throws KeyLengthException { 131 132 this(octJWK.toSecretKey("AES")); 133 } 134 135 136 /** 137 * Creates a new AES decrypter. 138 * 139 * @param kek The Key Encrypting Key. Must be 128 bits (16 140 * bytes), 192 bits (24 bytes) or 256 bits (32 141 * bytes). Must not be {@code null}. 142 * @param defCritHeaders The names of the critical header parameters 143 * that are deferred to the application for 144 * processing, empty set or {@code null} if none. 145 * 146 * @throws KeyLengthException If the KEK length is invalid. 147 */ 148 public AESDecrypter(final SecretKey kek, final Set<String> defCritHeaders) 149 throws KeyLengthException { 150 151 super(kek, null); 152 153 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 154 } 155 156 157 @Override 158 public Set<String> getProcessedCriticalHeaderParams() { 159 160 return critPolicy.getProcessedCriticalHeaderParams(); 161 } 162 163 164 @Override 165 public Set<String> getDeferredCriticalHeaderParams() { 166 167 return critPolicy.getProcessedCriticalHeaderParams(); 168 } 169 170 171 /** 172 * Decrypts the specified cipher text of a {@link JWEObject JWE Object}. 173 * 174 * @param header The JSON Web Encryption (JWE) header. Must 175 * specify a supported JWE algorithm and method. 176 * Must not be {@code null}. 177 * @param encryptedKey The encrypted key, {@code null} if not required 178 * by the JWE algorithm. 179 * @param iv The initialisation vector, {@code null} if not 180 * required by the JWE algorithm. 181 * @param cipherText The cipher text to decrypt. Must not be 182 * {@code null}. 183 * @param authTag The authentication tag, {@code null} if not 184 * required. 185 * 186 * @return The clear text. 187 * 188 * @throws JOSEException If the JWE algorithm or method is not 189 * supported, if a critical header parameter is 190 * not supported or marked for deferral to the 191 * application, or if decryption failed for some 192 * other reason. 193 */ 194 @Deprecated 195 public byte[] decrypt(final JWEHeader header, 196 final Base64URL encryptedKey, 197 final Base64URL iv, 198 final Base64URL cipherText, 199 final Base64URL authTag) 200 throws JOSEException { 201 202 return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header)); 203 } 204 205 206 @Override 207 public byte[] decrypt(final JWEHeader header, 208 final Base64URL encryptedKey, 209 final Base64URL iv, 210 final Base64URL cipherText, 211 final Base64URL authTag, 212 final byte[] aad) 213 throws JOSEException { 214 215 // Validate required JWE parts 216 if (encryptedKey == null) { 217 throw new JOSEException("Missing JWE encrypted key"); 218 } 219 220 if (iv == null) { 221 throw new JOSEException("Missing JWE initialization vector (IV)"); 222 } 223 224 if (authTag == null) { 225 throw new JOSEException("Missing JWE authentication tag"); 226 } 227 228 // Derive the content encryption key 229 JWEAlgorithm alg = JWEHeaderValidation.getAlgorithmAndEnsureNotNull(header); 230 231 critPolicy.ensureHeaderPasses(header); 232 233 int keyLength = header.getEncryptionMethod().cekBitLength(); 234 235 final SecretKey cek; 236 237 if (alg.equals(JWEAlgorithm.A128KW) || 238 alg.equals(JWEAlgorithm.A192KW) || 239 alg.equals(JWEAlgorithm.A256KW)) { 240 241 cek = AESKW.unwrapCEK(getKey(), encryptedKey.decode(), getJCAContext().getKeyEncryptionProvider()); 242 243 } else if (alg.equals(JWEAlgorithm.A128GCMKW) || 244 alg.equals(JWEAlgorithm.A192GCMKW) || 245 alg.equals(JWEAlgorithm.A256GCMKW)) { 246 247 if (header.getIV() == null) { 248 throw new JOSEException("Missing JWE \"iv\" header parameter"); 249 } 250 251 byte[] keyIV = header.getIV().decode(); 252 253 if (header.getAuthTag() == null) { 254 throw new JOSEException("Missing JWE \"tag\" header parameter"); 255 } 256 257 byte[] keyTag = header.getAuthTag().decode(); 258 259 AuthenticatedCipherText authEncrCEK = new AuthenticatedCipherText(encryptedKey.decode(), keyTag); 260 cek = AESGCMKW.decryptCEK(getKey(), keyIV, authEncrCEK, keyLength, getJCAContext().getKeyEncryptionProvider()); 261 262 } else { 263 264 throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); 265 } 266 267 return ContentCryptoProvider.decrypt(header, aad, encryptedKey, iv, cipherText, authTag, cek, getJCAContext()); 268 } 269}