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