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