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