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. 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 2014-06-29
040 */
041@ThreadSafe
042public class DirectEncrypter extends DirectCryptoProvider implements JWEEncrypter {
043
044
045        /**
046         * Creates a new direct encrypter.
047         *
048         * @param key The symmetric key. Its algorithm must be "AES". Must be
049         *            128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32
050         *            bytes), 384 bits (48 bytes) or 512 bits (64 bytes) long.
051         *            Must not be {@code null}.
052         *
053         * @throws KeyLengthException If the symmetric key length is not
054         *                            compatible.
055         */
056        public DirectEncrypter(final SecretKey key)
057                throws KeyLengthException {
058
059                super(key);
060        }
061
062
063        /**
064         * Creates a new direct encrypter.
065         *
066         * @param keyBytes The symmetric key, as a byte array. Must be 128 bits
067         *                 (16 bytes), 192 bits (24 bytes), 256 bits (32
068         *                 bytes), 384 bits (48 bytes) or 512 bits (64 bytes)
069         *                 long. Must not be {@code null}.
070         *
071         * @throws KeyLengthException If the symmetric key length is not
072         *                            compatible.
073         */
074        public DirectEncrypter(final byte[] keyBytes)
075                throws KeyLengthException {
076
077                this(new SecretKeySpec(keyBytes, "AES"));
078        }
079
080
081        /**
082         * Creates a new direct encrypter.
083         *
084         * @param octJWK The symmetric key, as a JWK. Must be 128 bits (16
085         *               bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384
086         *               bits (48 bytes) or 512 bits (64 bytes) long. Must not
087         *               be {@code null}.
088         *
089         * @throws KeyLengthException If the symmetric key length is not
090         *                            compatible.
091         */
092        public DirectEncrypter(final OctetSequenceKey octJWK)
093                throws KeyLengthException {
094
095                this(octJWK.toSecretKey("AES"));
096        }
097
098
099        @Override
100        public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText)
101                throws JOSEException {
102
103                JWEAlgorithm alg = header.getAlgorithm();
104
105                if (! alg.equals(JWEAlgorithm.DIR)) {
106                        throw new JOSEException(AlgorithmSupportMessage.unsupportedJWEAlgorithm(alg, SUPPORTED_ALGORITHMS));
107                }
108
109                // Check key length matches encryption method
110                EncryptionMethod enc = header.getEncryptionMethod();
111
112                if (enc.cekBitLength() != ByteUtils.bitLength(getKey().getEncoded())) {
113                        throw new KeyLengthException(enc.cekBitLength(), enc);
114                }
115
116                final Base64URL encryptedKey = null; // The second JWE part
117
118                return ContentCryptoProvider.encrypt(header, clearText, getKey(), encryptedKey, getJCAContext());
119        }
120}