001/*
002 * nimbus-jose-jwt
003 *
004 * Copyright 2012-2021, 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;
019
020
021import com.nimbusds.jose.*;
022import com.nimbusds.jose.crypto.impl.*;
023import com.nimbusds.jose.jwk.Curve;
024import com.nimbusds.jose.jwk.OctetKeyPair;
025import com.nimbusds.jose.util.Base64URL;
026import net.jcip.annotations.ThreadSafe;
027
028import javax.crypto.SecretKey;
029import java.util.Collections;
030import java.util.Set;
031
032
033/**
034 * Elliptic Curve Diffie-Hellman decrypter of
035 * {@link com.nimbusds.jose.JWEObject JWE objects} for curves using an OKP JWK.
036 * Expects a private {@link OctetKeyPair} key with {@code "crv"} X25519.
037 *
038 * <p>See <a href="https://tools.ietf.org/html/rfc8037">RFC 8037</a>
039 * for more information.
040 *
041 * <p>See also {@link ECDH1PUDecrypter} for ECDH on other curves.
042 *
043 * <p>Public Key Authenticated Encryption for JOSE
044 * <a href="https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04">ECDH-1PU</a>
045 * for more information.
046 *
047 * <p>This class is thread-safe.
048 *
049 * <p>Supports the following key management algorithms:
050 *
051 * <ul>
052 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU}
053 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A128KW}
054 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A192KW}
055 *     <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A256KW}
056 * </ul>
057 *
058 * <p>Supports the following elliptic curves:
059 *
060 * <ul>
061 *     <li>{@link Curve#X25519}
062 * </ul>
063 *
064 * <p>Supports the following content encryption algorithms for Direct key
065 * agreement mode:
066 *
067 * <ul>
068 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256}
069 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384}
070 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512}
071 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM}
072 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM}
073 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM}
074 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED}
075 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED}
076 *     <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P}
077 * </ul>
078 *
079 * <p>Supports the following content encryption algorithms for Key wrapping
080 * mode:
081 *
082 * <ul>
083 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256}
084 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384}
085 *     <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512}
086 * </ul>
087 *
088 * @author Alexander Martynov
089 * @author Egor Puzanov
090 * @version 2023-05-17
091 */
092@ThreadSafe
093public class ECDH1PUX25519Decrypter extends ECDH1PUCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware {
094
095
096    /**
097     * The private key.
098     */
099    private final OctetKeyPair privateKey;
100
101    /**
102     * The public key.
103     */
104    private final OctetKeyPair publicKey;
105
106    /**
107     * The critical header policy.
108     */
109    private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral();
110
111
112    /**
113     * Creates a new Curve25519 Elliptic Curve Diffie-Hellman decrypter.
114     *
115     * @param privateKey The private key. Must not be {@code null}.
116     * @param publicKey  The private key. Must not be {@code null}.
117     *
118     * @throws JOSEException If the key subtype is not supported.
119     */
120    public ECDH1PUX25519Decrypter(final OctetKeyPair privateKey, final OctetKeyPair publicKey)
121            throws JOSEException {
122
123        this(privateKey, publicKey, null);
124    }
125
126
127    /**
128     * Creates a new Curve25519 Elliptic Curve Diffie-Hellman decrypter.
129     *
130     * @param privateKey     The private key. Must not be {@code null}.
131     * @param publicKey      The private key. Must not be {@code null}.
132     * @param defCritHeaders The names of the critical header parameters
133     *                       that are deferred to the application for
134     *                       processing, empty set or {@code null} if none.
135     *
136     * @throws JOSEException If the key subtype is not supported.
137     */
138    public ECDH1PUX25519Decrypter(final OctetKeyPair privateKey,
139                                  final OctetKeyPair publicKey,
140                                  final Set<String> defCritHeaders)
141            throws JOSEException {
142
143        super(privateKey.getCurve(), null);
144
145        this.privateKey = privateKey;
146        this.publicKey = publicKey;
147
148        critPolicy.setDeferredCriticalHeaderParams(defCritHeaders);
149    }
150
151
152    @Override
153    public Set<Curve> supportedEllipticCurves() {
154
155        return Collections.singleton(Curve.X25519);
156    }
157
158
159    /**
160     * Returns the private key.
161     *
162     * @return The private key.
163     */
164    public OctetKeyPair getPrivateKey() {
165
166        return privateKey;
167    }
168
169    /**
170     * Returns the public key.
171     *
172     * @return The public key.
173     */
174    public OctetKeyPair getPublicKey() {
175
176        return publicKey;
177    }
178
179    @Override
180    public Set<String> getProcessedCriticalHeaderParams() {
181
182        return critPolicy.getProcessedCriticalHeaderParams();
183    }
184
185
186    @Override
187    public Set<String> getDeferredCriticalHeaderParams() {
188
189        return critPolicy.getProcessedCriticalHeaderParams();
190    }
191
192
193    /**
194     * Decrypts the specified cipher text of a {@link JWEObject JWE Object}.
195     *
196     * @param header       The JSON Web Encryption (JWE) header. Must
197     *                     specify a supported JWE algorithm and method.
198     *                     Must not be {@code null}.
199     * @param encryptedKey The encrypted key, {@code null} if not required
200     *                     by the JWE algorithm.
201     * @param iv           The initialisation vector, {@code null} if not
202     *                     required by the JWE algorithm.
203     * @param cipherText   The cipher text to decrypt. Must not be
204     *                     {@code null}.
205     * @param authTag      The authentication tag, {@code null} if not
206     *                     required.
207     *
208     * @return The clear text.
209     *
210     * @throws JOSEException If the JWE algorithm or method is not
211     *                       supported, if a critical header parameter is
212     *                       not supported or marked for deferral to the
213     *                       application, or if decryption failed for some
214     *                       other reason.
215     */
216    @Deprecated
217    public byte[] decrypt(final JWEHeader header,
218               final Base64URL encryptedKey,
219               final Base64URL iv,
220               final Base64URL cipherText,
221               final Base64URL authTag)
222        throws JOSEException {
223
224        return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header));
225    }
226
227
228    @Override
229    public byte[] decrypt(final JWEHeader header,
230                          final Base64URL encryptedKey,
231                          final Base64URL iv,
232                          final Base64URL cipherText,
233                          final Base64URL authTag,
234                          final byte[] aad)
235            throws JOSEException {
236
237        // Check for unrecognizable "crit" properties
238        critPolicy.ensureHeaderPasses(header);
239
240        // Get ephemeral key from header
241        OctetKeyPair ephemeralPublicKey = (OctetKeyPair) header.getEphemeralPublicKey();
242
243        if (ephemeralPublicKey == null) {
244            throw new JOSEException("Missing ephemeral public key \"epk\" JWE header parameter");
245        }
246
247        SecretKey Z = ECDH1PU.deriveRecipientZ(
248                privateKey,
249                publicKey,
250                ephemeralPublicKey
251        );
252
253        return decryptWithZ(header, aad, Z, encryptedKey, iv, cipherText, authTag);
254    }
255}