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 net.jcip.annotations.ThreadSafe;
026
027import com.nimbusds.jose.*;
028import com.nimbusds.jose.jwk.OctetSequenceKey;
029import com.nimbusds.jose.util.Base64URL;
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 * </ul>
060 * 
061 * @author Vladimir Dzhuvinov
062 * @version 2015-06-29
063 */
064@ThreadSafe
065public class DirectDecrypter extends DirectCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware {
066
067
068        /**
069         * The critical header policy.
070         */
071        private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral();
072
073
074        /**
075         * Creates a new direct decrypter.
076         *
077         * @param key The symmetric key. Its algorithm must be "AES". Must be
078         *            128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32
079         *            bytes), 384 bits (48 bytes) or 512 bits (64 bytes) long.
080         *            Must not be {@code null}.
081         *
082         * @throws KeyLengthException If the symmetric key length is not
083         *                            compatible.
084         */
085        public DirectDecrypter(final SecretKey key)
086                throws KeyLengthException {
087
088                super(key);
089        }
090
091
092        /**
093         * Creates a new direct decrypter.
094         *
095         * @param keyBytes The symmetric key, as a byte array. Must be 128 bits
096         *                 (16 bytes), 192 bits (24 bytes), 256 bits (32
097         *                 bytes), 384 bits (48 bytes) or 512 bits (64 bytes)
098         *                 long. Must not be {@code null}.
099         *
100         * @throws KeyLengthException If the symmetric key length is not
101         *                            compatible.
102         */
103        public DirectDecrypter(final byte[] keyBytes)
104                throws KeyLengthException {
105
106                this(new SecretKeySpec(keyBytes, "AES"));
107        }
108
109
110        /**
111         * Creates a new direct decrypter.
112         *
113         * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16
114         *               bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384
115         *               bits (48 bytes) or 512 bits (64 bytes) long. Must not
116         *               be {@code null}.
117         *
118         * @throws KeyLengthException If the symmetric key length is not
119         *                            compatible.
120         */
121        public DirectDecrypter(final OctetSequenceKey octJWK)
122                throws KeyLengthException {
123
124                this(octJWK.toSecretKey("AES"));
125        }
126
127
128        /**
129         * Creates a new direct decrypter.
130         *
131         * @param key            The symmetric key. Its algorithm must be
132         *                       "AES". Must be 128 bits (16 bytes), 192 bits
133         *                       (24 bytes), 256 bits (32 bytes), 384 bits (48
134         *                       bytes) or 512 bits (64 bytes) long. Must not
135         *                       be {@code null}.
136         * @param defCritHeaders The names of the critical header parameters
137         *                       that are deferred to the application for
138         *                       processing, empty set or {@code null} if none.
139         *
140         * @throws KeyLengthException If the symmetric key length is not
141         *                            compatible.
142         */
143        public DirectDecrypter(final SecretKey key, final Set<String> defCritHeaders)
144                throws KeyLengthException {
145
146                super(key);
147
148                critPolicy.setDeferredCriticalHeaderParams(defCritHeaders);
149        }
150
151
152        @Override
153        public Set<String> getProcessedCriticalHeaderParams() {
154
155                return critPolicy.getProcessedCriticalHeaderParams();
156        }
157
158
159        @Override
160        public Set<String> getDeferredCriticalHeaderParams() {
161
162                return critPolicy.getProcessedCriticalHeaderParams();
163        }
164
165
166        @Override
167        public byte[] decrypt(final JWEHeader header,
168                              final Base64URL encryptedKey,
169                              final Base64URL iv,
170                              final Base64URL cipherText,
171                              final Base64URL authTag) 
172                throws JOSEException {
173
174                // Validate required JWE parts
175                if (encryptedKey != null) {
176                        throw new JOSEException("Unexpected present JWE encrypted key");
177                }       
178
179                if (iv == null) {
180                        throw new JOSEException("Unexpected present JWE initialization vector (IV)");
181                }
182
183                if (authTag == null) {
184                        throw new JOSEException("Missing JWE authentication tag");
185                }
186                
187
188                JWEAlgorithm alg = header.getAlgorithm();
189
190                if (! alg.equals(JWEAlgorithm.DIR)) {
191                        throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS));
192                }
193
194                critPolicy.ensureHeaderPasses(header);
195
196                return ContentCryptoProvider.decrypt(header, null, iv, cipherText, authTag, getKey(), getJCAContext());
197        }
198}
199