com.nimbusds.jose.crypto.MultiEncrypter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of nimbus-jose-jwt Show documentation
Show all versions of nimbus-jose-jwt Show documentation
Java library for Javascript Object Signing and Encryption (JOSE) and
JSON Web Tokens (JWT)
/*
* nimbus-jose-jwt
*
* Copyright 2012-2016, Connect2id Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use
* this file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed
* under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
* CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package com.nimbusds.jose.crypto;
import com.nimbusds.jose.*;
import com.nimbusds.jose.crypto.impl.AAD;
import com.nimbusds.jose.crypto.impl.JWEHeaderValidation;
import com.nimbusds.jose.crypto.impl.MultiCryptoProvider;
import com.nimbusds.jose.jwk.JWK;
import com.nimbusds.jose.jwk.JWKSet;
import com.nimbusds.jose.jwk.KeyType;
import com.nimbusds.jose.util.Base64URL;
import com.nimbusds.jose.util.JSONArrayUtils;
import com.nimbusds.jose.util.JSONObjectUtils;
import net.jcip.annotations.ThreadSafe;
import javax.crypto.SecretKey;
import java.util.List;
import java.util.Map;
/**
* Multi-recipient encrypter of {@link com.nimbusds.jose.JWEObjectJSON JWE
* objects}.
*
* This class is thread-safe.
*
*
Supports the following key management algorithms:
*
*
* - {@link com.nimbusds.jose.JWEAlgorithm#A128KW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#A192KW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#A256KW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#A128GCMKW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#A192GCMKW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#A256GCMKW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#DIR}
*
- {@link com.nimbusds.jose.JWEAlgorithm#ECDH_ES_A128KW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#ECDH_ES_A192KW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#ECDH_ES_A256KW}
*
- {@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_256}
*
- {@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_384}
*
- {@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP_512}
*
- {@link com.nimbusds.jose.JWEAlgorithm#RSA_OAEP} (deprecated)
*
- {@link com.nimbusds.jose.JWEAlgorithm#RSA1_5} (deprecated)
*
*
* Supports the following elliptic curves:
*
*
* - {@link com.nimbusds.jose.jwk.Curve#P_256}
*
- {@link com.nimbusds.jose.jwk.Curve#P_384}
*
- {@link com.nimbusds.jose.jwk.Curve#P_521}
*
- {@link com.nimbusds.jose.jwk.Curve#X25519} (Curve25519)
*
*
* Supports the following content encryption algorithms:
*
*
* - {@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} (requires 256 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} (requires 384 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} (requires 512 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A128GCM} (requires 128 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A192GCM} (requires 192 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A256GCM} (requires 256 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} (requires 256 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} (requires 512 bit key)
*
- {@link com.nimbusds.jose.EncryptionMethod#XC20P} (requires 256 bit key)
*
*
* @author Egor Puzanov
* @author Vladimir Dzhuvinov
* @version 2024-04-20
*/
@ThreadSafe
public class MultiEncrypter extends MultiCryptoProvider implements JWEEncrypter {
/**
* Common JWK and JWEHeader parameters.
*/
private static final String[] RECIPIENT_HEADER_PARAMS = {
HeaderParameterNames.KEY_ID,
HeaderParameterNames.ALGORITHM,
HeaderParameterNames.X_509_CERT_URL,
HeaderParameterNames.X_509_CERT_SHA_1_THUMBPRINT,
HeaderParameterNames.X_509_CERT_SHA_256_THUMBPRINT,
HeaderParameterNames.X_509_CERT_CHAIN
};
/**
* The JWK public keys.
*/
private final JWKSet keys;
/**
* Creates a new multi-recipient encrypter.
*
* @param keys The keys to encrypt to. Must not be {@code null}.
*
* @throws KeyLengthException If the symmetric key length is not
* compatible.
*/
public MultiEncrypter(final JWKSet keys)
throws KeyLengthException {
this(keys, findDirectCEK(keys));
}
/**
* Creates a new multi-recipient encrypter.
*
* @param keys The keys to encrypt to. Must not be
* {@code null}.
* @param contentEncryptionKey The content encryption key (CEK) to use.
* If specified its algorithm must be "AES"
* or "ChaCha20" and its length must match
* the expected for the JWE encryption
* method ("enc"). If {@code null} a CEK
* will be generated for each JWE.
*
* @throws KeyLengthException If the symmetric key length is not
* compatible.
*/
public MultiEncrypter(final JWKSet keys, final SecretKey contentEncryptionKey)
throws KeyLengthException {
super(contentEncryptionKey);
for (JWK jwk : keys.getKeys()) {
KeyType kty = jwk.getKeyType();
if (jwk.getAlgorithm() == null) {
throw new IllegalArgumentException("Each JWK must specify a key encryption algorithm");
}
JWEAlgorithm alg = JWEAlgorithm.parse(jwk.getAlgorithm().toString());
if (JWEAlgorithm.DIR.equals(alg)
&& KeyType.OCT.equals(kty)
&& !jwk.toOctetSequenceKey().toSecretKey("AES").equals(contentEncryptionKey)) {
throw new IllegalArgumentException("Bad CEK");
}
if (!((KeyType.RSA.equals(kty) && RSAEncrypter.SUPPORTED_ALGORITHMS.contains(alg))
|| (KeyType.EC.equals(kty) && ECDHEncrypter.SUPPORTED_ALGORITHMS.contains(alg))
|| (KeyType.OCT.equals(kty) && AESEncrypter.SUPPORTED_ALGORITHMS.contains(alg))
|| (KeyType.OCT.equals(kty) && DirectEncrypter.SUPPORTED_ALGORITHMS.contains(alg))
|| (KeyType.OKP.equals(kty) && X25519Encrypter.SUPPORTED_ALGORITHMS.contains(alg)))) {
throw new IllegalArgumentException("Unsupported key encryption algorithm: " + alg);
}
}
this.keys = keys;
}
/**
* Returns the {@link SecretKey} of the recipients with
* {@link JWEAlgorithm#DIR} if present.
*
* @param keys The public keys. Must not be {@code null}.
*
* @return The SecretKey.
*/
private static SecretKey findDirectCEK(final JWKSet keys) {
if (keys != null) {
for (JWK jwk : keys.getKeys()) {
if (JWEAlgorithm.DIR.equals(jwk.getAlgorithm()) && KeyType.OCT.equals(jwk.getKeyType())) {
return jwk.toOctetSequenceKey().toSecretKey("AES");
}
}
}
return null;
}
/**
* Encrypts the specified clear text of a {@link JWEObject JWE object}.
*
* @param header The JSON Web Encryption (JWE) header. Must specify
* a supported JWE algorithm and method. Must not be
* {@code null}.
* @param clearText The clear text to encrypt. Must not be {@code null}.
*
* @return The resulting JWE crypto parts.
*
* @throws JOSEException If the JWE algorithm or method is not
* supported or if encryption failed for some
* other internal reason.
*/
@Deprecated
public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText)
throws JOSEException {
return encrypt(header, clearText, AAD.compute(header));
}
@Override
public JWECryptoParts encrypt(final JWEHeader header, final byte[] clearText, final byte[] aad)
throws JOSEException {
if (aad == null) {
throw new JOSEException("Missing JWE additional authenticated data (AAD)");
}
final EncryptionMethod enc = header.getEncryptionMethod();
final SecretKey cek = getCEK(enc);
JWECryptoParts jweParts;
JWEEncrypter encrypter;
JWEHeader recipientHeader = null;
Base64URL encryptedKey = null;
Base64URL cipherText = null;
Base64URL iv = null;
Base64URL tag = null;
JWEAlgorithm alg;
Payload payload = new Payload(clearText);
List
© 2015 - 2025 Weber Informatics LLC | Privacy Policy