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.OctetKeyPair; 028import com.nimbusds.jose.util.Base64URL; 029import net.jcip.annotations.ThreadSafe; 030 031import javax.crypto.SecretKey; 032import java.util.Collections; 033import java.util.Set; 034 035 036/** 037 * Elliptic Curve Diffie-Hellman decrypter of 038 * {@link com.nimbusds.jose.JWEObject JWE objects} for curves using an OKP JWK. 039 * Expects a private {@link OctetKeyPair} key with {@code "crv"} X25519. 040 * 041 * <p>See <a href="https://tools.ietf.org/html/rfc8037">RFC 8037</a> 042 * for more information. 043 * 044 * <p>See also {@link ECDH1PUDecrypter} for ECDH on other curves. 045 * 046 * <p>Public Key Authenticated Encryption for JOSE 047 * <a href="https://datatracker.ietf.org/doc/html/draft-madden-jose-ecdh-1pu-04">ECDH-1PU</a> 048 * for more information. 049 * 050 * <p>This class is thread-safe. 051 * 052 * <p>Supports the following key management algorithms: 053 * 054 * <ul> 055 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU} 056 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A128KW} 057 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A192KW} 058 * <li>{@link com.nimbusds.jose.JWEAlgorithm#ECDH_1PU_A256KW} 059 * </ul> 060 * 061 * <p>Supports the following elliptic curves: 062 * 063 * <ul> 064 * <li>{@link Curve#X25519} 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 * @version 2021-08-03 093 */ 094@ThreadSafe 095public class ECDH1PUX25519Decrypter extends ECDH1PUCryptoProvider implements JWEDecrypter, CriticalHeaderParamsAware { 096 097 098 /** 099 * The private key. 100 */ 101 private final OctetKeyPair privateKey; 102 103 /** 104 * The public key. 105 */ 106 private final OctetKeyPair publicKey; 107 108 /** 109 * The critical header policy. 110 */ 111 private final CriticalHeaderParamsDeferral critPolicy = new CriticalHeaderParamsDeferral(); 112 113 114 /** 115 * Creates a new Curve25519 Elliptic Curve Diffie-Hellman decrypter. 116 * 117 * @param privateKey The private key. Must not be {@code null}. 118 * @param publicKey The private key. Must not be {@code null}. 119 * 120 * @throws JOSEException If the key subtype is not supported. 121 */ 122 public ECDH1PUX25519Decrypter(final OctetKeyPair privateKey, final OctetKeyPair publicKey) 123 throws JOSEException { 124 125 this(privateKey, publicKey, null); 126 } 127 128 129 /** 130 * Creates a new Curve25519 Elliptic Curve Diffie-Hellman decrypter. 131 * 132 * @param privateKey The private key. Must not be {@code null}. 133 * @param publicKey The private key. Must not be {@code null}. 134 * @param defCritHeaders The names of the critical header parameters 135 * that are deferred to the application for 136 * processing, empty set or {@code null} if none. 137 * 138 * @throws JOSEException If the key subtype is not supported. 139 */ 140 public ECDH1PUX25519Decrypter(final OctetKeyPair privateKey, 141 final OctetKeyPair publicKey, 142 final Set<String> defCritHeaders) 143 throws JOSEException { 144 145 super(privateKey.getCurve()); 146 147 this.privateKey = privateKey; 148 this.publicKey = publicKey; 149 150 critPolicy.setDeferredCriticalHeaderParams(defCritHeaders); 151 } 152 153 154 @Override 155 public Set<Curve> supportedEllipticCurves() { 156 157 return Collections.singleton(Curve.X25519); 158 } 159 160 161 /** 162 * Returns the private key. 163 * 164 * @return The private key. 165 */ 166 public OctetKeyPair getPrivateKey() { 167 168 return privateKey; 169 } 170 171 /** 172 * Returns the public key. 173 * 174 * @return The public key. 175 */ 176 public OctetKeyPair getPublicKey() { 177 178 return publicKey; 179 } 180 181 @Override 182 public Set<String> getProcessedCriticalHeaderParams() { 183 184 return critPolicy.getProcessedCriticalHeaderParams(); 185 } 186 187 188 @Override 189 public Set<String> getDeferredCriticalHeaderParams() { 190 191 return critPolicy.getProcessedCriticalHeaderParams(); 192 } 193 194 195 @Override 196 public byte[] decrypt(final JWEHeader header, 197 final Base64URL encryptedKey, 198 final Base64URL iv, 199 final Base64URL cipherText, 200 final Base64URL authTag) 201 throws JOSEException { 202 203 // Check for unrecognizable "crit" properties 204 critPolicy.ensureHeaderPasses(header); 205 206 // Get ephemeral key from header 207 OctetKeyPair ephemeralPublicKey = (OctetKeyPair) header.getEphemeralPublicKey(); 208 209 if (ephemeralPublicKey == null) { 210 throw new JOSEException("Missing ephemeral public key \"epk\" JWE header parameter"); 211 } 212 213 SecretKey Z = ECDH1PU.deriveRecipientZ( 214 privateKey, 215 publicKey, 216 ephemeralPublicKey 217 ); 218 219 return decryptWithZ(header, Z, encryptedKey, iv, cipherText, authTag); 220 } 221}