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.ECKey; 025import com.nimbusds.jose.util.Base64URL; 026import net.jcip.annotations.ThreadSafe; 027 028import javax.crypto.SecretKey; 029import java.security.PrivateKey; 030import java.security.interfaces.ECPrivateKey; 031import java.security.interfaces.ECPublicKey; 032import java.util.Collections; 033import java.util.LinkedHashSet; 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 EC JWK. 040 * Expects a private EC key (with a P-256, P-384 or P-521 curve). 041 * 042 * <p>Public Key Authenticated Encryption for JOSE 043 * <a href="https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04">ECDH-1PU</a> 044 * for more information. 045 * 046 * <p>For Curve25519/X25519, see {@link ECDH1PUX25519Decrypter} instead. 047 * 048 * <p>This class is thread-safe. 049 * 050 * <p>Supports the following key management algorithms: 051 * 052 * <ul> 053 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU} 054 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A128KW} 055 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A192KW} 056 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A256KW} 057 * </ul> 058 * 059 * <p>Supports the following elliptic curves: 060 * 061 * <ul> 062 * <li>{@link Curve#P_256} 063 * <li>{@link Curve#P_384} 064 * <li>{@link Curve#P_521} 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 * @author Egor Puzanov 093 * @version 2026-02-19 094 */ 095@ThreadSafe 096public class ECDH1PUDecrypter extends ECDH1PUCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 097 098 099 /** 100 * The supported EC JWK curves by the ECDH crypto provider class. 101 */ 102 public static final Set<Curve> SUPPORTED_ELLIPTIC_CURVES; 103 104 105 static { 106 Set<Curve> curves = new LinkedHashSet<>(); 107 curves.add(Curve.P_256); 108 curves.add(Curve.P_384); 109 curves.add(Curve.P_521); 110 SUPPORTED_ELLIPTIC_CURVES = Collections.unmodifiableSet(curves); 111 } 112 113 114 /** 115 * The private EC key. 116 */ 117 private final ECPrivateKey privateKey; 118 119 /** 120 * The public EC key. 121 */ 122 private final ECPublicKey publicKey; 123 124 /** 125 * The critical header policy. 126 */ 127 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 128 129 130 /** 131 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 132 * 133 * @param privateKey The private EC key. Must not be {@code null}. 134 * @param publicKey The public EC key. Must not be {@code null}. 135 * @throws JOSEException If the elliptic curve is not supported. 136 */ 137 public ECDH1PUDecrypter(final ECPrivateKey privateKey, final ECPublicKey publicKey) 138 throws JOSEException { 139 140 this(privateKey, publicKey, null); 141 } 142 143 /** 144 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 145 * 146 * @param privateKey The private EC key. Must not be {@code null}. 147 * @param publicKey The public EC key. Must not be {@code null}. 148 * @param defCritHeaders The names of the critical header parameters 149 * that are deferred to the application for 150 * processing, empty set or {@code null} if none. 151 * @throws JOSEException If the elliptic curve is not supported. 152 */ 153 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 154 final ECPublicKey publicKey, 155 final Set<String> defCritHeaders) 156 throws JOSEException { 157 158 this(privateKey, publicKey, defCritHeaders, Curve.forECParameterSpec(privateKey.getParams())); 159 } 160 161 162 /** 163 * Creates a new Elliptic Curve Diffie-Hellman decrypter. This 164 * constructor can also accept a private EC key located in a PKCS#11 165 * store that doesn't expose the private key parameters (such as a 166 * smart card or HSM). 167 * 168 * @param privateKey The private EC key. Must not be {@code null}. 169 * @param publicKey The public EC key. Must not be {@code null}. 170 * @param defCritHeaders The names of the critical header parameters 171 * that are deferred to the application for 172 * processing, empty set or {@code null} if none. 173 * @param curve The key curve. Must not be {@code null}. 174 * @throws JOSEException If the elliptic curve is not supported. 175 */ 176 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 177 final ECPublicKey publicKey, 178 final Set<String> defCritHeaders, 179 final Curve curve) 180 throws JOSEException { 181 182 super(curve, null); 183 184 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 185 186 this.privateKey = privateKey; 187 this.publicKey = publicKey; 188 } 189 190 /** 191 * Returns the public EC key. 192 * 193 * @return The public EC key. 194 */ 195 public ECPublicKey getPublicKey() { 196 197 return publicKey; 198 } 199 200 /** 201 * Returns the private EC key. 202 * 203 * @return The private EC key. Casting to 204 * {@link ECPrivateKey} may not be 205 * possible if the key is located in a PKCS#11 store that 206 * doesn't expose the private key parameters. 207 */ 208 public PrivateKey getPrivateKey() { 209 210 return privateKey; 211 } 212 213 214 @Override 215 public Set<Curve> supportedEllipticCurves() { 216 217 return SUPPORTED_ELLIPTIC_CURVES; 218 } 219 220 221 @Override 222 public Set<String> getProcessedCriticalHeaderParams() { 223 224 return critPolicy.getProcessedCriticalHeaderParams(); 225 } 226 227 228 @Override 229 public Set<String> getDeferredCriticalHeaderParams() { 230 231 return critPolicy.getDeferredCriticalHeaderParams(); 232 } 233 234 235 /** 236 * Decrypts the specified cipher text of a {@link JWEObject JWE Object}. 237 * 238 * @param header The JSON Web Encryption (JWE) header. Must 239 * specify a supported JWE algorithm and method. 240 * Must not be {@code null}. 241 * @param encryptedKey The encrypted key, {@code null} if not required 242 * by the JWE algorithm. 243 * @param iv The initialisation vector, {@code null} if not 244 * required by the JWE algorithm. 245 * @param cipherText The cipher text to decrypt. Must not be 246 * {@code null}. 247 * @param authTag The authentication tag, {@code null} if not 248 * required. 249 * @return The clear text. 250 * @throws JOSEException If the JWE algorithm or method is not 251 * supported, if a critical header parameter is 252 * not supported or marked for deferral to the 253 * application, or if decryption failed for some 254 * other reason. 255 */ 256 @Deprecated 257 public byte[] decrypt(final JWEHeader header, 258 final Base64URL encryptedKey, 259 final Base64URL iv, 260 final Base64URL cipherText, 261 final Base64URL authTag) 262 throws JOSEException { 263 264 return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header)); 265 } 266 267 268 @Override 269 public byte[] decrypt(final JWEHeader header, 270 final Base64URL encryptedKey, 271 final Base64URL iv, 272 final Base64URL cipherText, 273 final Base64URL authTag, 274 final byte[] aad) 275 throws JOSEException { 276 277 critPolicy.ensureHeaderPasses(header); 278 279 // Get ephemeral EC key 280 ECKey ephemeralKey = (ECKey) header.getEphemeralPublicKey(); 281 282 if (ephemeralKey == null) { 283 throw new JOSEException("Missing ephemeral public EC key \"epk\" JWE header parameter"); 284 } 285 286 ECPublicKey ephemeralPublicKey = ephemeralKey.toECPublicKey(); 287 288 SecretKey Z = ECDH1PU.deriveRecipientZ( 289 privateKey, 290 publicKey, 291 ephemeralPublicKey, 292 getJCAContext().getKeyEncryptionProvider() 293 ); 294 295 return decryptWithZ(header, aad, Z, encryptedKey, iv, cipherText, authTag); 296 } 297}