001package com.nimbusds.jose.crypto; 002 003 004import java.util.Set; 005import javax.crypto.SecretKey; 006import javax.crypto.spec.SecretKeySpec; 007 008import net.jcip.annotations.ThreadSafe; 009 010import com.nimbusds.jose.*; 011import com.nimbusds.jose.jwk.OctetSequenceKey; 012import com.nimbusds.jose.util.Base64URL; 013 014 015/** 016 * Direct decrypter of {@link com.nimbusds.jose.JWEObject JWE objects} with a 017 * shared symmetric key. 018 * 019 * <p>See RFC 7518 020 * <a href="https://tools.ietf.org/html/rfc7518#section-4.5">section 4.5</a> 021 * for more information.</p> 022 * 023 * <p>This class is thread-safe. 024 * 025 * <p>Supports the following key management algorithms: 026 * 027 * <ul> 028 * <li>{@link com.nimbusds.jose.JWEAlgorithm#DIR} 029 * </ul> 030 * 031 * <p>Supports the following content encryption algorithms: 032 * 033 * <ul> 034 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 035 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 036 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 037 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} 038 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} 039 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} 040 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} 041 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} 042 * </ul> 043 * 044 * @author Vladimir Dzhuvinov 045 * @version 2015-06-29 046 */ 047@ThreadSafe 048public class DirectDecrypter extends DirectCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 049 050 051 /** 052 * The critical header policy. 053 */ 054 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 055 056 057 /** 058 * Creates a new direct decrypter. 059 * 060 * @param key The symmetric key. Its algorithm must be "AES". Must be 061 * 128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32 062 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) long. 063 * Must not be {@code null}. 064 * 065 * @throws KeyLengthException If the symmetric key length is not 066 * compatible. 067 */ 068 public DirectDecrypter(final SecretKey key) 069 throws KeyLengthException { 070 071 super(key); 072 } 073 074 075 /** 076 * Creates a new direct decrypter. 077 * 078 * @param keyBytes The symmetric key, as a byte array. Must be 128 bits 079 * (16 bytes), 192 bits (24 bytes), 256 bits (32 080 * bytes), 384 bits (48 bytes) or 512 bits (64 bytes) 081 * long. Must not be {@code null}. 082 * 083 * @throws KeyLengthException If the symmetric key length is not 084 * compatible. 085 */ 086 public DirectDecrypter(final byte[] keyBytes) 087 throws KeyLengthException { 088 089 this(new SecretKeySpec(keyBytes, "AES")); 090 } 091 092 093 /** 094 * Creates a new direct decrypter. 095 * 096 * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16 097 * bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384 098 * bits (48 bytes) or 512 bits (64 bytes) long. Must not 099 * be {@code null}. 100 * 101 * @throws KeyLengthException If the symmetric key length is not 102 * compatible. 103 */ 104 public DirectDecrypter(final OctetSequenceKey octJWK) 105 throws KeyLengthException { 106 107 this(octJWK.toSecretKey("AES")); 108 } 109 110 111 /** 112 * Creates a new direct decrypter. 113 * 114 * @param key The symmetric key. Its algorithm must be 115 * "AES". Must be 128 bits (16 bytes), 192 bits 116 * (24 bytes), 256 bits (32 bytes), 384 bits (48 117 * bytes) or 512 bits (64 bytes) long. Must not 118 * be {@code null}. 119 * @param defCritHeaders The names of the critical header parameters 120 * that are deferred to the application for 121 * processing, empty set or {@code null} if none. 122 * 123 * @throws KeyLengthException If the symmetric key length is not 124 * compatible. 125 */ 126 public DirectDecrypter(final SecretKey key, final Set<String> defCritHeaders) 127 throws KeyLengthException { 128 129 super(key); 130 131 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 132 } 133 134 135 @Override 136 public Set<String> getProcessedCriticalHeaderParams() { 137 138 return critPolicy.getProcessedCriticalHeaderParams(); 139 } 140 141 142 @Override 143 public Set<String> getDeferredCriticalHeaderParams() { 144 145 return critPolicy.getProcessedCriticalHeaderParams(); 146 } 147 148 149 @Override 150 public byte[] decrypt(final JWEHeader header, 151 final Base64URL encryptedKey, 152 final Base64URL iv, 153 final Base64URL cipherText, 154 final Base64URL authTag) 155 throws JOSEException { 156 157 // Validate required JWE parts 158 if (encryptedKey != null) { 159 throw new JOSEException("Unexpected present JWE encrypted key"); 160 } 161 162 if (iv == null) { 163 throw new JOSEException("Unexpected present JWE initialization vector (IV)"); 164 } 165 166 if (authTag == null) { 167 throw new JOSEException("Missing JWE authentication tag"); 168 } 169 170 171 JWEAlgorithm alg = header.getAlgorithm(); 172 173 if (! alg.equals(JWEAlgorithm.DIR)) { 174 throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS)); 175 } 176 177 critPolicy.ensureHeaderPasses(header); 178 179 return ContentCryptoProvider.decrypt(header, null, iv, cipherText, authTag, getKey(), getJCAContext()); 180 } 181} 182