001/* 002 * nimbus-jose-jwt 003 * 004 * Copyright 2012-2019, Connect2id Ltd. 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.proc; 019 020 021import com.nimbusds.jose.EncryptionMethod; 022import com.nimbusds.jose.JWEAlgorithm; 023import com.nimbusds.jose.JWEHeader; 024import com.nimbusds.jose.KeySourceException; 025import com.nimbusds.jose.jwk.JWK; 026import com.nimbusds.jose.jwk.JWKMatcher; 027import com.nimbusds.jose.jwk.JWKSelector; 028import com.nimbusds.jose.jwk.KeyConverter; 029import com.nimbusds.jose.jwk.source.JWKSource; 030import net.jcip.annotations.ThreadSafe; 031 032import javax.crypto.SecretKey; 033import java.security.Key; 034import java.security.PrivateKey; 035import java.util.Collections; 036import java.util.LinkedList; 037import java.util.List; 038import java.util.Objects; 039 040 041/** 042 * Key selector for decrypting JWE objects, where the key candidates are 043 * retrieved from a {@link JWKSource JSON Web Key (JWK) source}. 044 * 045 * @author Vladimir Dzhuvinov 046 * @version 2024-04-20 047 */ 048@ThreadSafe 049public class JWEDecryptionKeySelector<C extends SecurityContext> extends AbstractJWKSelectorWithSource<C> implements JWEKeySelector<C> { 050 051 052 /** 053 * The expected JWE algorithm. 054 */ 055 private final JWEAlgorithm jweAlg; 056 057 058 /** 059 * The expected JWE encryption method. 060 */ 061 private final EncryptionMethod jweEnc; 062 063 064 /** 065 * Creates a new decryption key selector. 066 * 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 not be {@code null}. 071 * @param jwkSource The JWK source. Must include the private keys and 072 * must not be {@code null}. 073 */ 074 public JWEDecryptionKeySelector(final JWEAlgorithm jweAlg, 075 final EncryptionMethod jweEnc, 076 final JWKSource<C> jwkSource) { 077 super(jwkSource); 078 this.jweAlg = Objects.requireNonNull(jweAlg); 079 this.jweEnc = Objects.requireNonNull(jweEnc); 080 } 081 082 083 /** 084 * Returns the expected JWE algorithm. 085 * 086 * @return The expected JWE algorithm. 087 */ 088 public JWEAlgorithm getExpectedJWEAlgorithm() { 089 return jweAlg; 090 } 091 092 093 /** 094 * The expected JWE encryption method. 095 * 096 * @return The expected JWE encryption method. 097 */ 098 public EncryptionMethod getExpectedJWEEncryptionMethod() { 099 return jweEnc; 100 } 101 102 103 /** 104 * Creates a JWK matcher for the expected JWE algorithms and the 105 * specified JWE header. 106 * 107 * @param jweHeader The JWE header. Must not be {@code null}. 108 * 109 * @return The JWK matcher, {@code null} if none could be created. 110 */ 111 protected JWKMatcher createJWKMatcher(final JWEHeader jweHeader) { 112 113 if (! getExpectedJWEAlgorithm().equals(jweHeader.getAlgorithm())) { 114 return null; 115 } 116 117 if (! getExpectedJWEEncryptionMethod().equals(jweHeader.getEncryptionMethod())) { 118 return null; 119 } 120 121 return JWKMatcher.forJWEHeader(jweHeader); 122 } 123 124 125 @Override 126 public List<Key> selectJWEKeys(final JWEHeader jweHeader, final C context) 127 throws KeySourceException { 128 129 if (! jweAlg.equals(jweHeader.getAlgorithm()) || ! jweEnc.equals(jweHeader.getEncryptionMethod())) { 130 // Unexpected JWE alg or enc 131 return Collections.emptyList(); 132 } 133 134 JWKMatcher jwkMatcher = createJWKMatcher(jweHeader); 135 List<JWK> jwkMatches = getJWKSource().get(new JWKSelector(jwkMatcher), context); 136 List<Key> sanitizedKeyList = new LinkedList<>(); 137 138 for (Key key: KeyConverter.toJavaKeys(jwkMatches)) { 139 if (key instanceof PrivateKey || key instanceof SecretKey) { 140 sanitizedKeyList.add(key); 141 } // skip public keys 142 } 143 144 return sanitizedKeyList; 145 } 146}