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