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.ECKey; 028import com.nimbusds.jose.util.Base64URL; 029import net.jcip.annotations.ThreadSafe; 030 031import javax.crypto.SecretKey; 032import java.security.PrivateKey; 033import java.security.interfaces.ECPrivateKey; 034import java.security.interfaces.ECPublicKey; 035import java.util.Collections; 036import java.util.LinkedHashSet; 037import java.util.Set; 038 039 040/** 041 * Elliptic Curve Diffie-Hellman decrypter of 042 * {@link com.nimbusds.jose.JWEObject JWE objects} for curves using an EC JWK. 043 * Expects a private EC key (with a P-256, P-384 or P-521 curve). 044 * 045 * <p>Public Key Authenticated Encryption for JOSE 046 * <a href="https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04">ECDH-1PU</a> 047 * for more information. 048 * 049 * <p>For Curve25519/X25519, see {@link ECDH1PUX25519Decrypter} instead. 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#P_256} 066 * <li>{@link Curve#P_384} 067 * <li>{@link Curve#P_521} 068 * </ul> 069 * 070 * <p>Supports the following content encryption algorithms for Direct key 071 * agreement mode: 072 * 073 * <ul> 074 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 075 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 076 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 077 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128GCM} 078 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192GCM} 079 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256GCM} 080 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256_DEPRECATED} 081 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512_DEPRECATED} 082 * <li>{@link com.nimbusds.jose.EncryptionMethod#XC20P} 083 * </ul> 084 * 085 * <p>Supports the following content encryption algorithms for Key wrapping 086 * mode: 087 * 088 * <ul> 089 * <li>{@link com.nimbusds.jose.EncryptionMethod#A128CBC_HS256} 090 * <li>{@link com.nimbusds.jose.EncryptionMethod#A192CBC_HS384} 091 * <li>{@link com.nimbusds.jose.EncryptionMethod#A256CBC_HS512} 092 * </ul> 093 * 094 * @author Alexander Martynov 095 * @version 2021-08-03 096 */ 097@ThreadSafe 098public class ECDH1PUDecrypter extends ECDH1PUCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 099 100 101 /** 102 * The supported EC JWK curves by the ECDH crypto provider class. 103 */ 104 public static final Set<Curve> SUPPORTED_ELLIPTIC_CURVES; 105 106 107 static { 108 Set<Curve> curves = new LinkedHashSet<>(); 109 curves.add(Curve.P_256); 110 curves.add(Curve.P_384); 111 curves.add(Curve.P_521); 112 SUPPORTED_ELLIPTIC_CURVES = Collections.unmodifiableSet(curves); 113 } 114 115 116 /** 117 * The private EC key. 118 */ 119 private final ECPrivateKey privateKey; 120 121 /** 122 * The public EC key. 123 */ 124 private final ECPublicKey publicKey; 125 126 /** 127 * The critical header policy. 128 */ 129 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 130 131 132 /** 133 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 134 * 135 * @param privateKey The private EC key. Must not be {@code null}. 136 * @param publicKey The public EC key. Must not be {@code null}. 137 * 138 * @throws JOSEException If the elliptic curve is not supported. 139 */ 140 public ECDH1PUDecrypter(final ECPrivateKey privateKey, final ECPublicKey publicKey) 141 throws JOSEException { 142 143 this(privateKey, publicKey, null); 144 } 145 146 /** 147 * Creates a new Elliptic Curve Diffie-Hellman decrypter. 148 * 149 * @param privateKey The private EC key. Must not be {@code null}. 150 * @param publicKey The public EC key. Must not be {@code null}. 151 * @param defCritHeaders The names of the critical header parameters 152 * that are deferred to the application for 153 * processing, empty set or {@code null} if none. 154 * 155 * @throws JOSEException If the elliptic curve is not supported. 156 */ 157 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 158 final ECPublicKey publicKey, 159 final Set<String> defCritHeaders) 160 throws JOSEException { 161 162 this(privateKey, publicKey, defCritHeaders, Curve.forECParameterSpec(privateKey.getParams())); 163 } 164 165 166 /** 167 * Creates a new Elliptic Curve Diffie-Hellman decrypter. This 168 * constructor can also accept a private EC key located in a PKCS#11 169 * store that doesn't expose the private key parameters (such as a 170 * smart card or HSM). 171 * 172 * @param privateKey The private EC key. Must not be {@code null}. 173 * @param publicKey The public EC key. Must not be {@code null}. 174 * @param defCritHeaders The names of the critical header parameters 175 * that are deferred to the application for 176 * processing, empty set or {@code null} if none. 177 * @param curve The key curve. Must not be {@code null}. 178 * 179 * @throws JOSEException If the elliptic curve is not supported. 180 */ 181 public ECDH1PUDecrypter(final ECPrivateKey privateKey, 182 final ECPublicKey publicKey, 183 final Set<String> defCritHeaders, 184 final Curve curve) 185 throws JOSEException { 186 187 super(curve); 188 189 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 190 191 this.privateKey = privateKey; 192 this.publicKey = publicKey; 193 } 194 195 /** 196 * Returns the public EC key. 197 * 198 * @return The public EC key. 199 */ 200 public ECPublicKey getPublicKey() { 201 202 return publicKey; 203 } 204 205 /** 206 * Returns the private EC key. 207 * 208 * @return The private EC key. Casting to 209 * {@link ECPrivateKey} may not be 210 * possible if the key is located in a PKCS#11 store that 211 * doesn't expose the private key parameters. 212 */ 213 public PrivateKey getPrivateKey() { 214 215 return privateKey; 216 } 217 218 219 @Override 220 public Set<Curve> supportedEllipticCurves() { 221 222 return SUPPORTED_ELLIPTIC_CURVES; 223 } 224 225 226 @Override 227 public Set<String> getProcessedCriticalHeaderParams() { 228 229 return critPolicy.getProcessedCriticalHeaderParams(); 230 } 231 232 233 @Override 234 public Set<String> getDeferredCriticalHeaderParams() { 235 236 return critPolicy.getProcessedCriticalHeaderParams(); 237 } 238 239 240 @Override 241 public byte[] decrypt(final JWEHeader header, 242 final Base64URL encryptedKey, 243 final Base64URL iv, 244 final Base64URL cipherText, 245 final Base64URL authTag) 246 throws JOSEException { 247 248 critPolicy.ensureHeaderPasses(header); 249 250 // Get ephemeral EC key 251 ECKey ephemeralKey = (ECKey) header.getEphemeralPublicKey(); 252 253 if (ephemeralKey == null) { 254 throw new JOSEException("Missing ephemeral public EC key \"epk\" JWE header parameter"); 255 } 256 257 ECPublicKey ephemeralPublicKey = ephemeralKey.toECPublicKey(); 258 259 SecretKey Z = ECDH1PU.deriveRecipientZ( 260 privateKey, 261 publicKey, 262 ephemeralPublicKey, 263 getJCAContext().getKeyEncryptionProvider() 264 ); 265 266 return decryptWithZ(header, Z, encryptedKey, iv, cipherText, authTag); 267 } 268}