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 2023-05-17 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 * 136 * @throws JOSEException If the elliptic curve is not supported. 137 */ 138 public ECDH1PUDecrypter(final ECPrivateKey privateKey, final ECPublicKey publicKey) 139 throws JOSEException { 140 141 this(privateKey, publicKey, null); 142 } 143 144 /** 145 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 146 * 147 * @param privateKey The private EC key. Must not be {@code null}. 148 * @param publicKey The public EC key. Must not be {@code null}. 149 * @param defCritHeaders The names of the critical header parameters 150 * that are deferred to the application for 151 * processing, empty set or {@code null} if none. 152 * 153 * @throws JOSEException If the elliptic curve is not supported. 154 */ 155 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 156 final ECPublicKey publicKey, 157 final Set<String> defCritHeaders) 158 throws JOSEException { 159 160 this(privateKey, publicKey, defCritHeaders, Curve.forECParameterSpec(privateKey.getParams())); 161 } 162 163 164 /** 165 * Creates a new Elliptic Curve Diffie-Hellman decrypter. This 166 * constructor can also accept a private EC key located in a PKCS#11 167 * store that doesn't expose the private key parameters (such as a 168 * smart card or HSM). 169 * 170 * @param privateKey The private EC key. Must not be {@code null}. 171 * @param publicKey The public EC key. Must not be {@code null}. 172 * @param defCritHeaders The names of the critical header parameters 173 * that are deferred to the application for 174 * processing, empty set or {@code null} if none. 175 * @param curve The key curve. Must not be {@code null}. 176 * 177 * @throws JOSEException If the elliptic curve is not supported. 178 */ 179 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 180 final ECPublicKey publicKey, 181 final Set<String> defCritHeaders, 182 final Curve curve) 183 throws JOSEException { 184 185 super(curve, null); 186 187 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 188 189 this.privateKey = privateKey; 190 this.publicKey = publicKey; 191 } 192 193 /** 194 * Returns the public EC key. 195 * 196 * @return The public EC key. 197 */ 198 public ECPublicKey getPublicKey() { 199 200 return publicKey; 201 } 202 203 /** 204 * Returns the private EC key. 205 * 206 * @return The private EC key. Casting to 207 * {@link ECPrivateKey} may not be 208 * possible if the key is located in a PKCS#11 store that 209 * doesn't expose the private key parameters. 210 */ 211 public PrivateKey getPrivateKey() { 212 213 return privateKey; 214 } 215 216 217 @Override 218 public Set<Curve> supportedEllipticCurves() { 219 220 return SUPPORTED_ELLIPTIC_CURVES; 221 } 222 223 224 @Override 225 public Set<String> getProcessedCriticalHeaderParams() { 226 227 return critPolicy.getProcessedCriticalHeaderParams(); 228 } 229 230 231 @Override 232 public Set<String> getDeferredCriticalHeaderParams() { 233 234 return critPolicy.getProcessedCriticalHeaderParams(); 235 } 236 237 238 /** 239 * Decrypts the specified cipher text of a {@link JWEObject JWE Object}. 240 * 241 * @param header The JSON Web Encryption (JWE) header. Must 242 * specify a supported JWE algorithm and method. 243 * Must not be {@code null}. 244 * @param encryptedKey The encrypted key, {@code null} if not required 245 * by the JWE algorithm. 246 * @param iv The initialisation vector, {@code null} if not 247 * required by the JWE algorithm. 248 * @param cipherText The cipher text to decrypt. Must not be 249 * {@code null}. 250 * @param authTag The authentication tag, {@code null} if not 251 * required. 252 * 253 * @return The clear text. 254 * 255 * @throws JOSEException If the JWE algorithm or method is not 256 * supported, if a critical header parameter is 257 * not supported or marked for deferral to the 258 * application, or if decryption failed for some 259 * other reason. 260 */ 261 @Deprecated 262 public byte[] decrypt(final JWEHeader header, 263 final Base64URL encryptedKey, 264 final Base64URL iv, 265 final Base64URL cipherText, 266 final Base64URL authTag) 267 throws JOSEException { 268 269 return decrypt(header, encryptedKey, iv, cipherText, authTag, AAD.compute(header)); 270 } 271 272 273 @Override 274 public byte[] decrypt(final JWEHeader header, 275 final Base64URL encryptedKey, 276 final Base64URL iv, 277 final Base64URL cipherText, 278 final Base64URL authTag, 279 final byte[] aad) 280 throws JOSEException { 281 282 critPolicy.ensureHeaderPasses(header); 283 284 // Get ephemeral EC key 285 ECKey ephemeralKey = (ECKey) header.getEphemeralPublicKey(); 286 287 if (ephemeralKey == null) { 288 throw new JOSEException("Missing ephemeral public EC key \"epk\" JWE header parameter"); 289 } 290 291 ECPublicKey ephemeralPublicKey = ephemeralKey.toECPublicKey(); 292 293 SecretKey Z = ECDH1PU.deriveRecipientZ( 294 privateKey, 295 publicKey, 296 ephemeralPublicKey, 297 getJCAContext().getKeyEncryptionProvider() 298 ); 299 300 return decryptWithZ(header, aad, Z, encryptedKey, iv, cipherText, authTag); 301 } 302}