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 javax.crypto.SecretKey;
022import javax.crypto.spec.SecretKeySpec;
023
024import com.nimbusds.jose.crypto.impl.AlgorithmSupportMessage;
025import com.nimbusds.jose.crypto.impl.ContentCryptoProvider;
026import com.nimbusds.jose.crypto.impl.DirectCryptoProvider;
027import net.jcip.annotations.ThreadSafe;
028
029import com.nimbusds.jose.*;
030import com.nimbusds.jose.jwk.OctetSequenceKey;
031import com.nimbusds.jose.util.Base64URL;
032import com.nimbusds.jose.util.ByteUtils;
033
034
035/**
036 * Direct encrypter of {@link com.nimbusds.jose.JWEObject JWE objects} with a
037 * shared symmetric key.
038 *
039 * <p>See RFC 7518
040 * <a href="https://tools.ietf.org/html/rfc7518#section-4.5">section 4.5</a>
041 * for more information.</p>
042 *
043 * <p>This class is thread-safe.
044 *
045 * <p>Supports the following key management algorithms:
046 *
047 * <ul>
048 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#DIR}
049 * </ul>
050 *
051 * <p>Supports the following content encryption algorithms:
052 *
053 * <ul>
054 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} (requires 256 bit key)
055 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} (requires 384 bit key)
056 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} (requires 512 bit key)
057 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} (requires 128 bit key)
058 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} (requires 192 bit key)
059 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} (requires 256 bit key)
060 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} (requires 256 bit key)
061 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} (requires 512 bit key)
062 *     <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} (requires 256 bit key)
063 * </ul>
064 *
065 * @author Vladimir Dzhuvinov
066 * @version 2017-06-01
067 */
068@ThreadSafe
069public class DirectEncrypter extends DirectCryptoProvider implements JWEEncrypter {
070
071
072        /**
073         * Creates a new direct encrypter.
074         *
075         * @param key The symmetric key. Its algorithm should be "AES". Must be
076         *            128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32
077         *            bytes), 384 bits (48 bytes) or 512 bits (64 bytes) long.
078         *            Must not be {@code null}.
079         *
080         * @throws KeyLengthException If the symmetric key length is not
081         *                            compatible.
082         */
083        public DirectEncrypter(final SecretKey key)
084                throws KeyLengthException {
085
086                super(key);
087        }
088
089
090        /**
091         * Creates a new direct encrypter.
092         *
093         * @param keyBytes The symmetric key, as a byte array. Must be 128 bits
094         *                 (16 bytes), 192 bits (24 bytes), 256 bits (32
095         *                 bytes), 384 bits (48 bytes) or 512 bits (64 bytes)
096         *                 long. Must not be {@code null}.
097         *
098         * @throws KeyLengthException If the symmetric key length is not
099         *                            compatible.
100         */
101        public DirectEncrypter(final byte[] keyBytes)
102                throws KeyLengthException {
103
104                this(new SecretKeySpec(keyBytes, "AES"));
105        }
106
107
108        /**
109         * Creates a new direct encrypter.
110         *
111         * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16
112         *               bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384
113         *               bits (48 bytes) or 512 bits (64 bytes) long. Must not
114         *               be {@code null}.
115         *
116         * @throws KeyLengthException If the symmetric key length is not
117         *                            compatible.
118         */
119        public DirectEncrypter(final OctetSequenceKey octJWK)
120                throws KeyLengthException {
121
122                this(octJWK.toSecretKey("AES"));
123        }
124
125
126        @Override
127        public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText)
128                throws JOSEException {
129
130                JWEAlgorithm alg = header.getAlgorithm();
131
132                if (! alg.equals(JWEAlgorithm.DIR)) {
133                        throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS));
134                }
135
136                // Check key length matches encryption method
137                EncryptionMethod enc = header.getEncryptionMethod();
138
139                if (enc.cekBitLength() != ByteUtils.safeBitLength(getKey().getEncoded())) {
140                        throw new KeyLengthException(enc.cekBitLength(), enc);
141                }
142
143                final Base64URL encryptedKey = null; // The second JWE part
144
145                return ContentCryptoProvider.encrypt(header, clearText, getKey(), encryptedKey, getJCAContext());
146        }
147}