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