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.*; 023import com.nimbusds.jose.crypto.opts.OptionUtils; 024import com.nimbusds.jose.jwk.Curve; 025import com.nimbusds.jose.jwk.ECKey; 026import com.nimbusds.jose.util.Base64URL; 027import net.jcip.annotations.ThreadSafe; 028 029import javax.crypto.SecretKey; 030import java.security.PrivateKey; 031import java.security.interfaces.ECPrivateKey; 032import java.security.interfaces.ECPublicKey; 033import java.util.Collections; 034import java.util.LinkedHashSet; 035import java.util.Set; 036 037 038/** 039 * Elliptic Curve Diffie-Hellman decrypter of 040 * {@link com.nimbusds.jose.JWEObject JWE objects} for curves using an EC JWK. 041 * Expects a private EC key (with a P-256, P-384 or P-521 curve). 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>For Curve25519/X25519, see {@link ECDH1PUX25519Decrypter} instead. 048 * 049 * <p>This class is thread-safe. 050 * 051 * <p>Supports the following key management algorithms: 052 * 053 * <ul> 054 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU} 055 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A128KW} 056 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A192KW} 057 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A256KW} 058 * </ul> 059 * 060 * <p>Supports the following elliptic curves: 061 * 062 * <ul> 063 * <li>{@link Curve#P_256} 064 * <li>{@link Curve#P_384} 065 * <li>{@link Curve#P_521} 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 * @version 2026-09-16 095 */ 096@ThreadSafe 097public class ECDH1PUDecrypter extends ECDH1PUCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 098 099 100 /** 101 * The supported EC JWK curves by the ECDH crypto provider class. 102 */ 103 public static final Set<Curve> SUPPORTED_ELLIPTIC_CURVES; 104 105 106 static { 107 Set<Curve> curves = new LinkedHashSet<>(); 108 curves.add(Curve.P_256); 109 curves.add(Curve.P_384); 110 curves.add(Curve.P_521); 111 SUPPORTED_ELLIPTIC_CURVES = Collections.unmodifiableSet(curves); 112 } 113 114 115 /** 116 * The private EC key. 117 */ 118 private final ECPrivateKey privateKey; 119 120 /** 121 * The public EC key. 122 */ 123 private final ECPublicKey publicKey; 124 125 /** 126 * The critical header policy. 127 */ 128 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 129 130 131 /** 132 * The configured options, empty set if none. 133 */ 134 private final Set<JWEDecrypterOption> opts; 135 136 137 /** 138 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 139 * 140 * @param privateKey The private EC key. Must not be {@code null}. 141 * @param publicKey The public EC key. Must not be {@code null}. 142 * 143 * @throws JOSEException If the elliptic curve is not supported. 144 */ 145 public ECDH1PUDecrypter(final ECPrivateKey privateKey, final ECPublicKey publicKey) 146 throws JOSEException { 147 148 this(privateKey, publicKey, null, Collections.<JWEDecrypterOption>emptySet()); 149 } 150 151 /** 152 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 153 * 154 * @param privateKey The private EC key. Must not be {@code null}. 155 * @param publicKey The public EC key. Must not be {@code null}. 156 * @param defCritHeaders The names of the critical header parameters 157 * that are deferred to the application for 158 * processing, empty set or {@code null} if none. 159 * 160 * @throws JOSEException If the elliptic curve is not supported. 161 */ 162 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 163 final ECPublicKey publicKey, 164 final Set<String> defCritHeaders) 165 throws JOSEException { 166 167 this(privateKey, publicKey, defCritHeaders, Curve.forECParameterSpec(privateKey.getParams()), Collections.<JWEDecrypterOption>emptySet()); 168 } 169 170 171 /** 172 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 173 * 174 * @param privateKey The private EC key. Must not be {@code null}. 175 * @param publicKey The public EC key. Must not be {@code null}. 176 * @param defCritHeaders The names of the critical header parameters 177 * that are deferred to the application for 178 * processing, empty set or {@code null} if none. 179 * @param opts The decryption options, empty or {@code null} 180 * if none. 181 * 182 * @throws JOSEException If the elliptic curve is not supported. 183 */ 184 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 185 final ECPublicKey publicKey, 186 final Set<String> defCritHeaders, 187 final Set<JWEDecrypterOption> opts) 188 throws JOSEException { 189 190 this(privateKey, publicKey, defCritHeaders, Curve.forECParameterSpec(privateKey.getParams()), opts); 191 } 192 193 194 /** 195 * Creates a new Elliptic Curve Diffie-Hellman decrypter. This 196 * constructor can also accept a private EC key located in a PKCS#11 197 * store that doesn't expose the private key parameters (such as a 198 * smart card or HSM). 199 * 200 * @param privateKey The private EC key. Must not be {@code null}. 201 * @param publicKey The public EC key. Must not be {@code null}. 202 * @param defCritHeaders The names of the critical header parameters 203 * that are deferred to the application for 204 * processing, empty set or {@code null} if none. 205 * @param curve The key curve. Must not be {@code null}. 206 * 207 * @throws JOSEException If the elliptic curve is not supported. 208 */ 209 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 210 final ECPublicKey publicKey, 211 final Set<String> defCritHeaders, 212 final Curve curve) 213 throws JOSEException { 214 215 this(privateKey, publicKey, defCritHeaders, curve, Collections.<JWEDecrypterOption>emptySet()); 216 } 217 218 219 /** 220 * Creates a new Elliptic Curve Diffie-Hellman decrypter. This 221 * constructor can also accept a private EC key located in a PKCS#11 222 * store that doesn't expose the private key parameters (such as a 223 * smart card or HSM). 224 * 225 * @param privateKey The private EC key. Must not be {@code null}. 226 * @param publicKey The public EC key. Must not be {@code null}. 227 * @param defCritHeaders The names of the critical header parameters 228 * that are deferred to the application for 229 * processing, empty set or {@code null} if none. 230 * @param curve The key curve. Must not be {@code null}. 231 * @param opts The decryption options, empty or {@code null} 232 * if none. 233 * 234 * @throws JOSEException If the elliptic curve is not supported. 235 */ 236 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 237 final ECPublicKey publicKey, 238 final Set<String> defCritHeaders, 239 final Curve curve, 240 final Set<JWEDecrypterOption> opts) 241 throws JOSEException { 242 243 super(curve, null); 244 245 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 246 247 this.privateKey = privateKey; 248 this.publicKey = publicKey; 249 this.opts = opts != null ? opts : Collections.<JWEDecrypterOption>emptySet(); 250 } 251 252 /** 253 * Returns the public EC key. 254 * 255 * @return The public EC key. 256 */ 257 public ECPublicKey getPublicKey() { 258 259 return publicKey; 260 } 261 262 263 /** 264 * Returns the private EC key. 265 * 266 * @return The private EC key. Casting to 267 * {@link ECPrivateKey} may not be 268 * possible if the key is located in a PKCS#11 store that 269 * doesn't expose the private key parameters. 270 */ 271 public PrivateKey getPrivateKey() { 272 273 return privateKey; 274 } 275 276 277 @Override 278 public Set<Curve> supportedEllipticCurves() { 279 280 return SUPPORTED_ELLIPTIC_CURVES; 281 } 282 283 284 @Override 285 public Set<String> getProcessedCriticalHeaderParams() { 286 287 return critPolicy.getProcessedCriticalHeaderParams(); 288 } 289 290 291 @Override 292 public Set<String> getDeferredCriticalHeaderParams() { 293 294 return critPolicy.getDeferredCriticalHeaderParams(); 295 } 296 297 298 /** 299 * Decrypts the specified cipher text of a {@link JWEObject JWE Object}. 300 * 301 * @param header The JSON Web Encryption (JWE) header. Must 302 * specify a supported JWE algorithm and method. 303 * Must not be {@code null}. 304 * @param encryptedKey The encrypted key, {@code null} if not required 305 * by the JWE algorithm. 306 * @param iv The initialisation vector, {@code null} if not 307 * required by the JWE algorithm. 308 * @param cipherText The cipher text to decrypt. Must not be 309 * {@code null}. 310 * @param authTag The authentication tag, {@code null} if not 311 * required. 312 * @return The clear text. 313 * @throws JOSEException If the JWE algorithm or method is not 314 * supported, if a critical header parameter is 315 * not supported or marked for deferral to the 316 * application, or if decryption failed for some 317 * other reason. 318 */ 319 @Deprecated 320 public byte[] decrypt(final JWEHeader header, 321 final Base64URL encryptedKey, 322 final Base64URL iv, 323 final Base64URL cipherText, 324 final Base64URL authTag) 325 throws JOSEException { 326 327 return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header)); 328 } 329 330 331 @Override 332 public byte[] decrypt(final JWEHeader header, 333 final Base64URL encryptedKey, 334 final Base64URL iv, 335 final Base64URL cipherText, 336 final Base64URL authTag, 337 final byte[] aad) 338 throws JOSEException { 339 340 critPolicy.ensureHeaderPasses(header); 341 342 // Get ephemeral EC key 343 ECKey ephemeralKey = (ECKey) header.getEphemeralPublicKey(); 344 345 if (ephemeralKey == null) { 346 throw new JOSEException("Missing ephemeral public EC key \"epk\" JWE header parameter"); 347 } 348 349 ECPublicKey ephemeralPublicKey = ephemeralKey.toECPublicKey(); 350 351 SecretKey Z = ECDH1PU.deriveRecipientZ( 352 privateKey, 353 publicKey, 354 ephemeralPublicKey, 355 getJCAContext().getKeyEncryptionProvider() 356 ); 357 358 int maxDecompressedLength = OptionUtils.resolveMaxDecompressedPlainTextLength(opts); 359 360 return decryptWithZ(header, aad, Z, encryptedKey, iv, cipherText, authTag, maxDecompressedLength); 361 } 362}