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