001package com.nimbusds.jose.proc; 002 003 004import java.security.Key; 005import java.security.PrivateKey; 006import java.util.Collections; 007import java.util.LinkedList; 008import java.util.List; 009 010import javax.crypto.SecretKey; 011 012import com.nimbusds.jose.EncryptionMethod; 013import com.nimbusds.jose.JWEAlgorithm; 014import com.nimbusds.jose.JWEHeader; 015import com.nimbusds.jose.jwk.*; 016import com.nimbusds.jose.jwk.source.JWKSource; 017import net.jcip.annotations.ThreadSafe; 018 019 020/** 021 * Key selector for decrypting JWE objects, where the key candidates are 022 * retrieved from a {@link JWKSource JSON Web Key (JWK) source}. 023 * 024 * @author Vladimir Dzhuvinov 025 * @version 2016-04-10 026 */ 027@ThreadSafe 028public class JWEDecryptionKeySelector<C extends SecurityContext> extends AbstractJWKSelectorWithSource<C> implements JWEKeySelector<C> { 029 030 031 /** 032 * The expected JWE algorithm. 033 */ 034 private final JWEAlgorithm jweAlg; 035 036 037 /** 038 * The expected JWE encryption method. 039 */ 040 private final EncryptionMethod jweEnc; 041 042 043 /** 044 * Creates a new decryption key selector. 045 * 046 * @param jweAlg The expected JWE algorithm for the objects to be 047 * decrypted. Must not be {@code null}. 048 * @param jweEnc The expected JWE encryption method for the objects 049 * to be decrypted. Must not be {@code null}. 050 * @param jwkSource The JWK source. Must include the private keys and 051 * must not be {@code null}. 052 */ 053 public JWEDecryptionKeySelector(final JWEAlgorithm jweAlg, 054 final EncryptionMethod jweEnc, 055 final JWKSource<C> jwkSource) { 056 super(jwkSource); 057 if (jweAlg == null) { 058 throw new IllegalArgumentException("The JWE algorithm must not be null"); 059 } 060 this.jweAlg = jweAlg; 061 if (jweEnc == null) { 062 throw new IllegalArgumentException("The JWE encryption method must not be null"); 063 } 064 this.jweEnc = jweEnc; 065 } 066 067 068 /** 069 * Returns the expected JWE algorithm. 070 * 071 * @return The expected JWE algorithm. 072 */ 073 public JWEAlgorithm getExpectedJWEAlgorithm() { 074 return jweAlg; 075 } 076 077 078 /** 079 * The expected JWE encryption method. 080 * 081 * @return The expected JWE encryption method. 082 */ 083 public EncryptionMethod getExpectedJWEEncryptionMethod() { 084 return jweEnc; 085 } 086 087 088 /** 089 * Creates a JWK matcher for the expected JWE algorithms and the 090 * specified JWE header. 091 * 092 * @param jweHeader The JWE header. Must not be {@code null}. 093 * 094 * @return The JWK matcher, {@code null} if none could be created. 095 */ 096 protected JWKMatcher createJWKMatcher(final JWEHeader jweHeader) { 097 098 if (! getExpectedJWEAlgorithm().equals(jweHeader.getAlgorithm())) { 099 return null; 100 } 101 102 if (! getExpectedJWEEncryptionMethod().equals(jweHeader.getEncryptionMethod())) { 103 return null; 104 } 105 106 return new JWKMatcher.Builder() 107 .keyType(KeyType.forAlgorithm(getExpectedJWEAlgorithm())) 108 .keyID(jweHeader.getKeyID()) 109 .keyUses(KeyUse.ENCRYPTION, null) 110 .algorithms(getExpectedJWEAlgorithm(), null) 111 .build(); 112 } 113 114 115 @Override 116 public List<Key> selectJWEKeys(final JWEHeader jweHeader, final C context) { 117 118 if (! jweAlg.equals(jweHeader.getAlgorithm()) || ! jweEnc.equals(jweHeader.getEncryptionMethod())) { 119 // Unexpected JWE alg or enc 120 return Collections.emptyList(); 121 } 122 123 JWKMatcher jwkMatcher = createJWKMatcher(jweHeader); 124 List<JWK> jwkMatches = getJWKSource().get(new JWKSelector(jwkMatcher), context); 125 List<Key> sanitizedKeyList = new LinkedList<>(); 126 127 for (Key key: KeyConverter.toJavaKeys(jwkMatches)) { 128 if (key instanceof PrivateKey || key instanceof SecretKey) { 129 sanitizedKeyList.add(key); 130 } // skip public keys 131 } 132 133 return sanitizedKeyList; 134 } 135}