001package com.nimbusds.oauth2.sdk.jose.jwk; 002 003 004import java.security.Key; 005import java.security.PrivateKey; 006import java.util.Collections; 007import java.util.LinkedList; 008import java.util.List; 009 010import com.nimbusds.jose.EncryptionMethod; 011import com.nimbusds.jose.JWEAlgorithm; 012import com.nimbusds.jose.JWEHeader; 013import com.nimbusds.jose.jwk.*; 014import com.nimbusds.jose.proc.JWEKeySelector; 015import com.nimbusds.jose.proc.SecurityContext; 016import com.nimbusds.oauth2.sdk.id.Identifier; 017import net.jcip.annotations.ThreadSafe; 018 019 020/** 021 * Key selector for decrypting JWE objects used in OpenID Connect. 022 * 023 * <p>Can be used to select RSA and EC key candidates for the decryption of: 024 * 025 * <ul> 026 * <li>Encrypted ID tokens 027 * <li>Encrypted JWT-encoded UserInfo responses 028 * <li>Encrypted OpenID request objects 029 * </ul> 030 */ 031@ThreadSafe 032@Deprecated 033public class JWEDecryptionKeySelector extends AbstractJWKSelectorWithSource implements JWEKeySelector { 034 035 036 /** 037 * The expected JWE algorithm. 038 */ 039 private final JWEAlgorithm jweAlg; 040 041 042 /** 043 * The expected JWE encryption method. 044 */ 045 private final EncryptionMethod jweEnc; 046 047 048 /** 049 * Ensures the specified JWE algorithm is RSA or EC based. 050 * 051 * @param jweAlg The JWE algorithm to check. 052 */ 053 private static void ensureAsymmetricEncryptionAlgorithm(final JWEAlgorithm jweAlg) { 054 055 if (! JWEAlgorithm.Family.RSA.contains(jweAlg) && ! JWEAlgorithm.Family.ECDH_ES.contains(jweAlg)) { 056 throw new IllegalArgumentException("The JWE algorithm must be RSA or EC based"); 057 } 058 } 059 060 061 /** 062 * Creates a new decryption key selector. 063 * 064 * @param id Identifier for the JWE recipient, typically an 065 * OAuth 2.0 server issuer ID, or client ID. Must not 066 * be {@code null}. 067 * @param jweAlg The expected JWE algorithm for the objects to be 068 * decrypted. Must not be {@code null}. 069 * @param jweEnc The expected JWE encryption method for the objects 070 * to be decrypted. Must be RSA or EC based. Must not 071 * be {@code null}. 072 * @param jwkSource The JWK source. Must include the private keys and 073 * must not be {@code null}. 074 */ 075 public JWEDecryptionKeySelector(final Identifier id, 076 final JWEAlgorithm jweAlg, 077 final EncryptionMethod jweEnc, 078 final JWKSource jwkSource) { 079 super(id, jwkSource); 080 if (jweAlg == null) { 081 throw new IllegalArgumentException("The JWE algorithm must not be null"); 082 } 083 ensureAsymmetricEncryptionAlgorithm(jweAlg); 084 this.jweAlg = jweAlg; 085 if (jweEnc == null) { 086 throw new IllegalArgumentException("The JWE encryption method must not be null"); 087 } 088 this.jweEnc = jweEnc; 089 } 090 091 092 /** 093 * Returns the expected JWE algorithm. 094 * 095 * @return The expected JWE algorithm. 096 */ 097 public JWEAlgorithm getExpectedJWEAlgorithm() { 098 return jweAlg; 099 } 100 101 102 /** 103 * The expected JWE encryption method. 104 * 105 * @return The expected JWE encryption method. 106 */ 107 public EncryptionMethod getExpectedJWEEncryptionMethod() { 108 return jweEnc; 109 } 110 111 112 /** 113 * Creates a JWK matcher for the expected JWE algorithms and the 114 * specified JWE header. 115 * 116 * @param jweHeader The JWE header. Must not be {@code null}. 117 * 118 * @return The JWK matcher, {@code null} if none could be created. 119 */ 120 protected JWKMatcher createJWKMatcher(final JWEHeader jweHeader) { 121 122 if (! getExpectedJWEAlgorithm().equals(jweHeader.getAlgorithm())) { 123 return null; 124 } 125 126 if (! getExpectedJWEEncryptionMethod().equals(jweHeader.getEncryptionMethod())) { 127 return null; 128 } 129 130 return new JWKMatcher.Builder() 131 .keyType(KeyType.forAlgorithm(getExpectedJWEAlgorithm())) 132 .keyID(jweHeader.getKeyID()) 133 .keyUses(KeyUse.ENCRYPTION, null) 134 .algorithms(getExpectedJWEAlgorithm(), null) 135 .build(); 136 } 137 138 139 @Override 140 public List<Key> selectJWEKeys(final JWEHeader jweHeader, final SecurityContext context) { 141 142 if (! jweAlg.equals(jweHeader.getAlgorithm()) || ! jweEnc.equals(jweHeader.getEncryptionMethod())) { 143 // Unexpected JWE alg or enc 144 return Collections.emptyList(); 145 } 146 147 JWKMatcher jwkMatcher = createJWKMatcher(jweHeader); 148 List<JWK> jwkMatches = getJWKSource().get(getIdentifier(), new JWKSelector(jwkMatcher)); 149 150 List<Key> sanitizedKeyList = new LinkedList<>(); 151 152 for (Key key: KeyConverter.toJavaKeys(jwkMatches)) { 153 if (key instanceof PrivateKey) { 154 sanitizedKeyList.add(key); 155 } // skip public keys 156 } 157 158 return sanitizedKeyList; 159 } 160}