001package com.nimbusds.jose.crypto;
002
003
004import javax.crypto.SecretKey;
005import javax.crypto.spec.SecretKeySpec;
006
007import net.jcip.annotations.ThreadSafe;
008
009import com.nimbusds.jose.*;
010import com.nimbusds.jose.jwk.OctetSequenceKey;
011import com.nimbusds.jose.util.Base64URL;
012import com.nimbusds.jose.util.ByteUtils;
013
014
015/**
016 * Direct encrypter 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 2014-06-29
046 */
047@ThreadSafe
048public class DirectEncrypter extends DirectCryptoProvider implements JWEEncrypter {
049
050
051        /**
052         * Creates a new direct encrypter.
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 DirectEncrypter(final SecretKey key)
063                throws KeyLengthException {
064
065                super(key);
066        }
067
068
069        /**
070         * Creates a new direct encrypter.
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 DirectEncrypter(final byte[] keyBytes)
081                throws KeyLengthException {
082
083                this(new SecretKeySpec(keyBytes, "AES"));
084        }
085
086
087        /**
088         * Creates a new direct encrypter.
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 DirectEncrypter(final OctetSequenceKey octJWK)
099                throws KeyLengthException {
100
101                this(octJWK.toSecretKey("AES"));
102        }
103
104
105        @Override
106        public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText)
107                throws JOSEException {
108
109                JWEAlgorithm alg = header.getAlgorithm();
110
111                if (! alg.equals(JWEAlgorithm.DIR)) {
112                        throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS));
113                }
114
115                // Check key length matches encryption method
116                EncryptionMethod enc = header.getEncryptionMethod();
117
118                if (enc.cekBitLength() != ByteUtils.bitLength(getKey().getEncoded())) {
119                        throw new KeyLengthException(enc.cekBitLength(), enc);
120                }
121
122                final Base64URL encryptedKey = null; // The second JWE part
123
124                return ContentCryptoProvider.encrypt(header, clearText, getKey(), encryptedKey, getJCAContext());
125        }
126}