001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2016, Connect2id Ltd and contributors.
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.impl;
019
020
021import com.nimbusds.jose.EncryptionMethod;
022import com.nimbusds.jose.JWEAlgorithm;
023import com.nimbusds.jose.KeyLengthException;
024import com.nimbusds.jose.util.ByteUtils;
025
026import javax.crypto.SecretKey;
027import java.util.Collections;
028import java.util.LinkedHashSet;
029import java.util.Set;
030
031
032/**
033 * The base abstract class for direct encrypters and decrypters of
034 * {@link com.nimbusds.jose.JWEObject JWE objects} with a shared symmetric key.
035 *
036 * <p>Supports the following key management algorithms:
037 *
038 * <ul>
039 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#DIR}
040 * </ul>
041 *
042 * <p>Supports the following content encryption algorithms:
043 *
044 * <ul>
045 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256}
046 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384}
047 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512}
048 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM}
049 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM}
050 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM}
051 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED}
052 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED}
053 *     <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P}
054 * </ul>
055 * 
056 * @author Vladimir Dzhuvinov
057 * @version 2023-07-11
058 */
059public abstract class DirectCryptoProvider extends BaseJWEProvider {
060
061
062        /**
063         * The supported JWE algorithms by the direct crypto provider class.
064         */
065        public static final Set<JWEAlgorithm> SUPPORTED_ALGORITHMS;
066
067
068        /**
069         * The supported encryption methods by the direct crypto provider
070         * class.
071         */
072        public static final Set<EncryptionMethod> SUPPORTED_ENCRYPTION_METHODS = ContentCryptoProvider.SUPPORTED_ENCRYPTION_METHODS;
073
074
075        static {
076                Set<JWEAlgorithm> algs = new LinkedHashSet<>();
077                algs.add(JWEAlgorithm.DIR);
078                SUPPORTED_ALGORITHMS = Collections.unmodifiableSet(algs);
079        }
080
081
082        /**
083         * Returns the compatible encryption methods for the specified Content
084         * Encryption Key (CEK) length.
085         *
086         * @param cekBitLength The CEK length in bits.
087         *
088         * @return The compatible encryption methods.
089         *
090         * @throws KeyLengthException If the CEK length is not compatible.
091         */
092        private static Set<EncryptionMethod> getCompatibleEncryptionMethods(final int cekBitLength)
093                throws KeyLengthException {
094
095                if (cekBitLength == 0) {
096                        // Suspect HSM that doesn't expose key material, return all supported enc AES/GCM methods
097                        // https://bitbucket.org/connect2id/nimbus-jose-jwt/issues/490/jwe-with-shared-key-support-for-android
098                        return EncryptionMethod.Family.AES_GCM;
099                }
100                
101                Set<EncryptionMethod> encs = ContentCryptoProvider.COMPATIBLE_ENCRYPTION_METHODS.get(cekBitLength);
102
103                if (encs == null) {
104                        throw new KeyLengthException("The Content Encryption Key length must be 128 bits (16 bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384 bits (48 bytes) or 512 bites (64 bytes)");
105                }
106
107                return encs;
108        }
109
110
111        /**
112         * Creates a new direct encryption / decryption provider.
113         *
114         * @param cek The Content Encryption Key (CEK). Must be 128 bits (16
115         *            bytes), 192 bits (24 bytes), 256 bits (32 bytes), 384
116         *            bits (48 bytes) or 512 bits (64 bytes) long. Must not be
117         *            {@code null}.
118         *
119         * @throws KeyLengthException If the CEK length is not compatible.
120         */
121        protected DirectCryptoProvider(final SecretKey cek)
122                throws KeyLengthException {
123
124                super(SUPPORTED_ALGORITHMS, getCompatibleEncryptionMethods(ByteUtils.bitLength(cek.getEncoded())), cek);
125        }
126
127
128        /**
129         * Gets the Content Encryption Key (CEK).
130         *
131         * @return The key.
132         */
133        public SecretKey getKey() {
134                try {
135                        return getCEK(null);
136                } catch (Exception e) {
137                        return null;
138                }
139        }
140}