[java-opensaml] branch main updated: OSJ-362: Add support for dynamic config to Decrypter
Brent Putman
putmanb at georgetown.edu
Mon Jul 31 23:17:59 UTC 2023
This is an automated email from the git hooks/post-receive script.
putmanb pushed a commit to branch main
in repository java-opensaml.
View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=f8212e464d29e9a9c3c16478318361464f9bd71c
The following commit(s) were added to refs/heads/main by this push:
new f8212e464 OSJ-362: Add support for dynamic config to Decrypter
f8212e464 is described below
commit f8212e464d29e9a9c3c16478318361464f9bd71c
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Wed May 31 20:59:34 2023 -0400
OSJ-362: Add support for dynamic config to Decrypter
---
.../action/impl/PopulateDecryptionParameters.java | 31 +++++-
.../EncryptedElementTypeEncryptedKeyResolver.java | 19 ++--
.../saml2/profile/impl/AbstractDecryptAction.java | 3 +-
...cryptedElementTypeEncryptedKeyResolverTest.java | 77 +++++++++-----
.../opensaml/xmlsec/DecryptionConfiguration.java | 9 ++
.../org/opensaml/xmlsec/DecryptionParameters.java | 23 ++++
.../criterion/DecryptionRecipientsCriterion.java | 116 +++++++++++++++++++++
.../support/AbstractEncryptedKeyResolver.java | 33 ++++--
.../support/ChainingEncryptedKeyResolver.java | 28 +++--
.../xmlsec/encryption/support/Decrypter.java | 45 +++++++-
.../encryption/support/EncryptedKeyResolver.java | 18 +++-
.../support/InlineEncryptedKeyResolver.java | 21 ++--
...SimpleKeyInfoReferenceEncryptedKeyResolver.java | 21 +++-
.../SimpleRetrievalMethodEncryptedKeyResolver.java | 11 +-
.../xmlsec/impl/BasicDecryptionConfiguration.java | 23 ++++
.../impl/BasicDecryptionParametersResolver.java | 34 ++++++
.../tests/ChainingEncryptedKeyResolverTest.java | 70 ++++++++++---
.../tests/InlineEncryptedKeyResolverTest.java | 69 ++++++++----
...leKeyInfoReferenceEncryptedKeyResolverTest.java | 59 ++++++++---
...pleRetrievalMethodEncryptedKeyResolverTest.java | 74 +++++++++----
.../BasicDecryptionParametersResolverTest.java | 53 ++++++++++
21 files changed, 685 insertions(+), 152 deletions(-)
diff --git a/opensaml-profile-impl/src/main/java/org/opensaml/profile/action/impl/PopulateDecryptionParameters.java b/opensaml-profile-impl/src/main/java/org/opensaml/profile/action/impl/PopulateDecryptionParameters.java
index 02f9ddd0c..adcf2b725 100644
--- a/opensaml-profile-impl/src/main/java/org/opensaml/profile/action/impl/PopulateDecryptionParameters.java
+++ b/opensaml-profile-impl/src/main/java/org/opensaml/profile/action/impl/PopulateDecryptionParameters.java
@@ -21,6 +21,7 @@ import java.util.List;
import java.util.function.Function;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.messaging.context.navigate.ChildContextLookup;
import org.opensaml.profile.action.AbstractConditionalProfileAction;
@@ -34,6 +35,7 @@ import org.opensaml.xmlsec.DecryptionParametersResolver;
import org.opensaml.xmlsec.SecurityConfigurationSupport;
import org.opensaml.xmlsec.context.SecurityParametersContext;
import org.opensaml.xmlsec.criterion.DecryptionConfigurationCriterion;
+import org.opensaml.xmlsec.criterion.DecryptionRecipientsCriterion;
import org.slf4j.Logger;
import net.shibboleth.shared.annotation.constraint.NonnullAfterInit;
@@ -65,6 +67,9 @@ public class PopulateDecryptionParameters extends AbstractConditionalProfileActi
/** Resolver for parameters to store into context. */
@NonnullAfterInit private DecryptionParametersResolver resolver;
+
+ /** Strategy used to look up the {@link SecurityParametersContext} to set the parameters for. */
+ @Nullable private Function<ProfileRequestContext,String> recipientLookupStrategy;
/**
* Constructor.
@@ -102,6 +107,18 @@ public class PopulateDecryptionParameters extends AbstractConditionalProfileActi
"DecryptionConfiguration lookup strategy cannot be null");
}
+ /**
+ * Set the strategy used to look up the dynamic recipient to include in decryption criteria.
+ *
+ * @param strategy to use
+ */
+ public void setRecipientLookupStrategy(
+ @Nullable final Function<ProfileRequestContext,String> strategy) {
+ checkSetterPreconditions();
+
+ recipientLookupStrategy = strategy;
+ }
+
/**
* Set the resolver to use for the parameters to store into the context.
*
@@ -151,10 +168,18 @@ public class PopulateDecryptionParameters extends AbstractConditionalProfileActi
return;
}
+ String recipient = null;
+ if (recipientLookupStrategy != null) {
+ recipient = recipientLookupStrategy.apply(profileRequestContext);
+ log.debug("{} Resolved dynamic recipient for decryption: {}", getLogPrefix(), recipient);
+ }
+
try {
-
- final DecryptionParameters params = resolver.resolveSingle(
- new CriteriaSet(new DecryptionConfigurationCriterion(configs)));
+ final CriteriaSet criteria = new CriteriaSet(new DecryptionConfigurationCriterion(configs));
+ if (recipient != null) {
+ criteria.add(new DecryptionRecipientsCriterion(CollectionSupport.singleton(recipient)));
+ }
+ final DecryptionParameters params = resolver.resolveSingle(criteria);
paramsCtx.setDecryptionParameters(params);
log.debug("{} {} DecryptionParameters", getLogPrefix(),
params != null ? "Resolved" : "Failed to resolve");
diff --git a/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/encryption/EncryptedElementTypeEncryptedKeyResolver.java b/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/encryption/EncryptedElementTypeEncryptedKeyResolver.java
index 6b96e59a5..1a1a3db70 100644
--- a/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/encryption/EncryptedElementTypeEncryptedKeyResolver.java
+++ b/opensaml-saml-api/src/main/java/org/opensaml/saml/saml2/encryption/EncryptedElementTypeEncryptedKeyResolver.java
@@ -20,6 +20,7 @@ package org.opensaml.saml.saml2.encryption;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -48,6 +49,7 @@ public class EncryptedElementTypeEncryptedKeyResolver extends AbstractEncryptedK
*
* @param recipients the set of recipients
*/
+ @Deprecated
public EncryptedElementTypeEncryptedKeyResolver(@Nullable final Set<String> recipients) {
super(recipients);
}
@@ -57,27 +59,24 @@ public class EncryptedElementTypeEncryptedKeyResolver extends AbstractEncryptedK
*
* @param recipient the recipient
*/
+ @Deprecated
public EncryptedElementTypeEncryptedKeyResolver(@Nullable final String recipient) {
this(recipient != null ? CollectionSupport.singleton(recipient) : null);
}
/** {@inheritDoc} */
- @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData) {
- final List<EncryptedKey> resolvedEncKeys = new ArrayList<>();
+ @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData,
+ @Nullable final Set<String> recipients) {
if (!(encryptedData.getParent() instanceof EncryptedElementType) ) {
- return resolvedEncKeys;
+ return CollectionSupport.emptyList();
}
final EncryptedElementType encElementType = (EncryptedElementType) encryptedData.getParent();
assert encElementType != null;
- for (final EncryptedKey encKey : encElementType.getEncryptedKeys()) {
- if (matchRecipient(encKey.getRecipient())) {
- resolvedEncKeys.add(encKey);
- }
- }
-
- return resolvedEncKeys;
+ return encElementType.getEncryptedKeys().stream()
+ .filter(ek -> matchRecipient(ek.getRecipient(), getEffectiveRecipients(recipients)))
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
}
}
\ No newline at end of file
diff --git a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/AbstractDecryptAction.java b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/AbstractDecryptAction.java
index 8bad22de7..d688cfeaa 100644
--- a/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/AbstractDecryptAction.java
+++ b/opensaml-saml-impl/src/main/java/org/opensaml/saml/saml2/profile/impl/AbstractDecryptAction.java
@@ -197,8 +197,7 @@ public abstract class AbstractDecryptAction extends AbstractProfileAction {
if (params == null) {
log.debug("{} No security parameter context or decryption parameters", getLogPrefix());
} else {
- decrypter = new Decrypter(params.getDataKeyInfoCredentialResolver(),
- params.getKEKKeyInfoCredentialResolver(), params.getEncryptedKeyResolver());
+ decrypter = new Decrypter(params);
}
return true;
diff --git a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/encryption/tests/EncryptedElementTypeEncryptedKeyResolverTest.java b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/encryption/tests/EncryptedElementTypeEncryptedKeyResolverTest.java
index 133207027..5fae95963 100644
--- a/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/encryption/tests/EncryptedElementTypeEncryptedKeyResolverTest.java
+++ b/opensaml-saml-impl/src/test/java/org/opensaml/saml/saml2/encryption/tests/EncryptedElementTypeEncryptedKeyResolverTest.java
@@ -17,17 +17,13 @@
package org.opensaml.saml.saml2.encryption.tests;
-import org.testng.annotations.Test;
-
-import net.shibboleth.shared.collection.CollectionSupport;
-
-import org.testng.Assert;
-
-import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.core.testing.XMLObjectBaseTestCase;
import org.opensaml.saml.saml2.core.EncryptedAssertion;
@@ -35,6 +31,10 @@ import org.opensaml.saml.saml2.encryption.EncryptedElementTypeEncryptedKeyResolv
import org.opensaml.xmlsec.encryption.EncryptedData;
import org.opensaml.xmlsec.encryption.EncryptedKey;
import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.collection.CollectionSupport;
/**
* Test the SAML EncryptedElementType encrypted key resolver, with keys as peers.
@@ -61,7 +61,7 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, null);
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -82,9 +82,9 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
List<EncryptedKey> allKeys = encAssertion.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new EncryptedElementTypeEncryptedKeyResolver(new HashSet<>(CollectionSupport.listOf("foo", "bar", "baz")));
+ resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.setOf("foo", "bar", "baz"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -105,9 +105,9 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
List<EncryptedKey> allKeys = encAssertion.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new EncryptedElementTypeEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -128,9 +128,9 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
List<EncryptedKey> allKeys = encAssertion.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new EncryptedElementTypeEncryptedKeyResolver(CollectionSupport.singleton("bar"));
+ resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("bar"));
Assert.assertEquals(resolved.size(), 0, "Incorrect number of resolved EncryptedKeys found");
}
@@ -150,7 +150,7 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, null);
Assert.assertEquals(resolved.size(), 4, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -174,9 +174,9 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
List<EncryptedKey> allKeys = encAssertion.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new EncryptedElementTypeEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -197,9 +197,34 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
List<EncryptedKey> allKeys = encAssertion.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new EncryptedElementTypeEncryptedKeyResolver(new HashSet<>(CollectionSupport.listOf("foo", "baz")));
+ resolver = new EncryptedElementTypeEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.setOf("foo", "baz"));
+ Assert.assertEquals(resolved.size(), 3, "Incorrect number of resolved EncryptedKeys found");
+
+ Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(1) == allKeys.get(2), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(2) == allKeys.get(3), "Unexpected EncryptedKey instance found");
+ }
+
+ /** Multi recipient specified to resolver via ctor and method args. */
+ @Test
+ @SuppressWarnings("deprecation")
+ public void testMultiRecipientsCtorAndArgs() {
+ String filename = "/org/opensaml/saml/saml2/encryption/EncryptedElementTypeEncryptedKeyResolverMultiple.xml";
+ final EncryptedAssertion encAssertion = (EncryptedAssertion) unmarshallElement(filename);
+ assert encAssertion != null;
+
+ Assert.assertNotNull(encAssertion.getEncryptedData());
+ final EncryptedData encData = encAssertion.getEncryptedData();
+ assert encData != null;
+
+ List<EncryptedKey> allKeys = encAssertion.getEncryptedKeys();
+ Assert.assertFalse(allKeys.isEmpty());
+
+ resolver = new EncryptedElementTypeEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("baz"));
Assert.assertEquals(resolved.size(), 3, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -212,14 +237,14 @@ public class EncryptedElementTypeEncryptedKeyResolverTest extends XMLObjectBaseT
*
* @param encData the EncryptedData context
* @param ekResolver the resolver to test
+ * @param recipients the valid recipients for resolution
* @return list of resolved EncryptedKeys
*/
- @Nonnull private List<EncryptedKey> generateList(@Nonnull final EncryptedData encData, @Nonnull final EncryptedKeyResolver ekResolver) {
- List<EncryptedKey> resolved = new ArrayList<>();
- for (EncryptedKey encKey : ekResolver.resolve(encData)) {
- resolved.add(encKey);
- }
- return resolved;
+ @Nonnull private List<EncryptedKey> generateList(@Nonnull final EncryptedData encData,
+ @Nonnull final EncryptedKeyResolver ekResolver, @Nullable final Set<String> recipients) {
+
+ return StreamSupport.stream(ekResolver.resolve(encData, recipients).spliterator(), false)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
}
}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionConfiguration.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionConfiguration.java
index fdbf48cea..d50b450d0 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionConfiguration.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionConfiguration.java
@@ -17,6 +17,8 @@
package org.opensaml.xmlsec;
+import java.util.Set;
+
import javax.annotation.Nullable;
import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
@@ -49,4 +51,11 @@ public interface DecryptionConfiguration extends AlgorithmPolicyConfiguration {
*/
@Nullable EncryptedKeyResolver getEncryptedKeyResolver();
+ /**
+ * Get the set of recipients against which to evaluate candidate EncryptedKey elements.
+ *
+ * @return the recipients
+ */
+ @Nullable Set<String> getRecipients();
+
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionParameters.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionParameters.java
index 9f759ed8e..13680eeb1 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionParameters.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/DecryptionParameters.java
@@ -17,6 +17,8 @@
package org.opensaml.xmlsec;
+import java.util.Set;
+
import javax.annotation.Nullable;
import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
@@ -35,6 +37,9 @@ public class DecryptionParameters extends AlgorithmPolicyParameters {
/** The EncryptedKey resolver. */
@Nullable private EncryptedKeyResolver encryptedKeyResolver;
+
+ /** The set of recipients against which to evaluate candidate EncryptedKey elements. */
+ @Nullable private Set<String> recipients;
/**
* Get the KeyInfoCredentialResolver to use when processing the EncryptedData/KeyInfo.
@@ -91,5 +96,23 @@ public class DecryptionParameters extends AlgorithmPolicyParameters {
public void setEncryptedKeyResolver(@Nullable final EncryptedKeyResolver resolver) {
encryptedKeyResolver = resolver;
}
+
+ /**
+ * Get the set of recipients against which to evaluate candidate EncryptedKey elements.
+ *
+ * @return the recipients
+ */
+ public @Nullable Set<String> getRecipients() {
+ return recipients;
+ }
+
+ /**
+ * Set the set of recipients against which to evaluate candidate EncryptedKey elements.
+ *
+ * @param newRecipients the recipients
+ */
+ public void setRecipients(@Nullable Set<String> newRecipients) {
+ recipients = newRecipients;
+ }
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/criterion/DecryptionRecipientsCriterion.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/criterion/DecryptionRecipientsCriterion.java
new file mode 100644
index 000000000..5b9ac76bc
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/criterion/DecryptionRecipientsCriterion.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.opensaml.xmlsec.criterion;
+
+import java.util.Set;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
+import net.shibboleth.shared.primitive.StringSupport;
+import net.shibboleth.shared.resolver.Criterion;
+
+/**
+ * A criterion implementation for conveying set of recipients against which to evaluate candidate
+ * EncryptedKey elements.
+ */
+public class DecryptionRecipientsCriterion implements Criterion {
+
+ /** The set of recipients. */
+ @Nonnull private Set<String> recipients;
+
+ /**
+ * Constructor.
+ *
+ * @param values the set of recipients
+ */
+ public DecryptionRecipientsCriterion(@Nullable final Set<String> values) {
+ recipients = processValues(values);
+ }
+
+ /**
+ * Get the set of recipients
+ *
+ * @return the set of recipients
+ */
+ @Nonnull @NotLive @Unmodifiable public Set<String> getRecipients() {
+ return recipients;
+ }
+
+ /**
+ * Set the set of recipients
+ *
+ * @param values the new recipients
+ */
+ public void setRecipients(@Nullable final Set<String> values) {
+ recipients = processValues(values);
+ }
+
+ /** {@inheritDoc} */
+ public String toString() {
+ final StringBuilder builder = new StringBuilder();
+ builder.append("DecryptionRecipientsCriterion [values=");
+ builder.append(recipients);
+ builder.append("]");
+ return builder.toString();
+ }
+
+ /** {@inheritDoc} */
+ public int hashCode() {
+ int result = 17;
+ result = 37*result + recipients.hashCode();
+ return result;
+ }
+
+ /** {@inheritDoc} */
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+
+ if (obj == null) {
+ return false;
+ }
+
+ if (obj instanceof DecryptionRecipientsCriterion) {
+ final DecryptionRecipientsCriterion other = (DecryptionRecipientsCriterion) obj;
+ return recipients.equals(other.recipients);
+ }
+
+ return false;
+ }
+
+ /**
+ * Sanitize input values.
+ *
+ * @param values input values
+ *
+ * @return sanitized set
+ */
+ @Nonnull @NotLive @Unmodifiable private Set<String> processValues(@Nullable final Set<String> values) {
+ if (values!= null) {
+ return CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(values));
+ } else {
+ return CollectionSupport.emptySet();
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/AbstractEncryptedKeyResolver.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/AbstractEncryptedKeyResolver.java
index c65cbc640..650a0876f 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/AbstractEncryptedKeyResolver.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/AbstractEncryptedKeyResolver.java
@@ -17,6 +17,7 @@
package org.opensaml.xmlsec.encryption.support;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
@@ -57,6 +58,7 @@ public abstract class AbstractEncryptedKeyResolver implements EncryptedKeyResolv
*
* @param newRecipents set of recipients
*/
+ @Deprecated
public AbstractEncryptedKeyResolver(@Nullable final Set<String> newRecipents) {
recipients = CollectionSupport.copyToSet(StringSupport.normalizeStringCollection(newRecipents));
}
@@ -76,29 +78,48 @@ public abstract class AbstractEncryptedKeyResolver implements EncryptedKeyResolv
}
/** {@inheritDoc} */
+ @Deprecated
@Nonnull @Unmodifiable @NotLive public Set<String> getRecipients() {
return recipients;
}
+ /**
+ * Get the effective set of recipients by merging the passed recipients set
+ * with the static set of recipients possibly configured on this resolver instance.
+ *
+ * @param values the recipients argument
+ * @return the merged recipients
+ */
+ @Nonnull @Unmodifiable @NotLive
+ protected Set<String> getEffectiveRecipients(@Nullable Set<String> values) {
+ final Set<String> temp = new HashSet<>();
+ temp.addAll(getRecipients());
+ if (values != null) {
+ temp.addAll(values);
+ }
+ return CollectionSupport.copyToSet(temp);
+ }
+
/**
* Evaluate whether the specified recipient attribute value matches this resolver's
* recipient criteria.
*
* @param recipient the recipient value to evaluate
+ * @param validRecipients recipients to consider valid for matching purposes.
+ * If empty, then all recipients match
* @return true if the recipient value matches the resolver's criteria, false otherwise
*/
- protected boolean matchRecipient(@Nullable final String recipient) {
- final String trimmedRecipient = StringSupport.trimOrNull(recipient);
- if (trimmedRecipient == null) {
+ protected boolean matchRecipient(@Nullable final String recipient, @Nonnull Set<String> validRecipients) {
+ if (validRecipients.isEmpty()) {
return true;
}
- final Set<String> ourRecipients = getRecipients();
- if (ourRecipients.isEmpty()) {
+ final String trimmedRecipient = StringSupport.trimOrNull(recipient);
+ if (trimmedRecipient == null) {
return true;
}
- return ourRecipients.contains(trimmedRecipient);
+ return validRecipients.contains(trimmedRecipient);
}
/**
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/ChainingEncryptedKeyResolver.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/ChainingEncryptedKeyResolver.java
index 6bf3679ba..437f00449 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/ChainingEncryptedKeyResolver.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/ChainingEncryptedKeyResolver.java
@@ -65,6 +65,7 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
* @param encKeyResolvers the chain of encrypted key resolvers
* @param recipients the set of recipients
*/
+ @Deprecated
public ChainingEncryptedKeyResolver(
@Nonnull @ParameterName(name="encKeyResolvers") final List<EncryptedKeyResolver> encKeyResolvers,
@Nullable @ParameterName(name="recipients") final Set<String> recipients) {
@@ -79,6 +80,7 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
* @param encKeyResolvers the chain of encrypted key resolvers
* @param recipient the recipient
*/
+ @Deprecated
public ChainingEncryptedKeyResolver(
@Nonnull @ParameterName(name="encKeyResolvers") final List<EncryptedKeyResolver> encKeyResolvers,
@Nullable @ParameterName(name="recipient") final String recipient) {
@@ -96,12 +98,13 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
/** {@inheritDoc} */
@Override
- @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData) {
+ @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData,
+ @Nullable final Set<String> recipients) {
if (resolvers.isEmpty()) {
log.warn("Chaining encrypted key resolver resolution was attempted with an empty resolver chain");
throw new IllegalStateException("The resolver chain is empty");
}
- return new ChainingIterable(this, encryptedData);
+ return new ChainingIterable(this, encryptedData, recipients);
}
/**
@@ -114,22 +117,28 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
/** The EncryptedData context for resolution. */
@Nonnull private final EncryptedData encryptedData;
+
+ /** The recipients for resolution. */
+ @Nullable private final Set<String> recipients;
/**
* Constructor.
*
* @param resolver the ChainingEncryptedKeyResolver parent
* @param encData the EncryptedData context for resolution
+ * @param recipientIDs the recipients for resolution
*/
public ChainingIterable(@Nonnull final ChainingEncryptedKeyResolver resolver,
- @Nonnull final EncryptedData encData) {
+ @Nonnull final EncryptedData encData, @Nullable final Set<String> recipientIDs) {
parent = resolver;
encryptedData = encData;
+ recipients = recipientIDs;
+
}
/** {@inheritDoc} */
@Nonnull public Iterator<EncryptedKey> iterator() {
- return new ChainingIterator(parent, encryptedData);
+ return new ChainingIterator(parent, encryptedData, recipients);
}
}
@@ -150,6 +159,9 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
/** The EncryptedData context for resolution. */
@Nonnull private final EncryptedData encryptedData;
+ /** The recipients for resolution. */
+ @Nonnull @Unmodifiable @NotLive private final Set<String> validRecipients;
+
/** The iterator over resolvers in the chain. */
@Nonnull private final Iterator<EncryptedKeyResolver> resolverIterator;
@@ -167,11 +179,13 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
*
* @param resolver the ChainingEncryptedKeyResolver parent
* @param encData the EncryptedData context for resolution
+ * @param recipientIDs the recipients for resolution
*/
public ChainingIterator(@Nonnull final ChainingEncryptedKeyResolver resolver,
- @Nonnull final EncryptedData encData) {
+ @Nonnull final EncryptedData encData, @Nullable final Set<String> recipientIDs) {
parent = resolver;
encryptedData = encData;
+ validRecipients = getEffectiveRecipients(recipientIDs);
resolverIterator = parent.getResolverChain().iterator();
keyIterator = getNextKeyIterator();
nextKey = null;
@@ -239,7 +253,7 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
if (keyIterator != null) {
while (keyIterator.hasNext()) {
tempKey = keyIterator.next();
- if (parent.matchRecipient(tempKey.getRecipient())) {
+ if (parent.matchRecipient(tempKey.getRecipient(), validRecipients)) {
log.debug("Found matching encrypted key: {}", tempKey.toString());
return tempKey;
}
@@ -250,7 +264,7 @@ public class ChainingEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
while (keyIterator != null) {
while (keyIterator.hasNext()) {
tempKey = keyIterator.next();
- if (parent.matchRecipient(tempKey.getRecipient())) {
+ if (parent.matchRecipient(tempKey.getRecipient(), validRecipients)) {
log.debug("Found matching encrypted key: {}", tempKey.toString());
return tempKey;
}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/Decrypter.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/Decrypter.java
index a6719006d..3d70d5f48 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/Decrypter.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/Decrypter.java
@@ -205,6 +205,9 @@ public class Decrypter {
/** Resolver for EncryptedKey instances which contain the encrypted data encryption key. */
@Nullable private EncryptedKeyResolver encKeyResolver;
+ /** The set of recipients against which to evaluate candidate EncryptedKey elements. */
+ @Nullable private Set<String> recipients;
+
/** The collection of algorithm URIs which are included. */
@Nullable private Collection<String> includedAlgorithmURIs;
@@ -236,6 +239,7 @@ public class Decrypter {
this( params.getDataKeyInfoCredentialResolver(),
params.getKEKKeyInfoCredentialResolver(),
params.getEncryptedKeyResolver(),
+ params.getRecipients(),
params.getIncludedAlgorithms(),
params.getExcludedAlgorithms()
);
@@ -252,7 +256,23 @@ public class Decrypter {
@Nullable final KeyInfoCredentialResolver newKEKResolver,
@Nullable final EncryptedKeyResolver newEncKeyResolver) {
- this(newResolver, newKEKResolver, newEncKeyResolver, null, null);
+ this(newResolver, newKEKResolver, newEncKeyResolver, null, null, null);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param newResolver resolver for data encryption keys.
+ * @param newKEKResolver resolver for key encryption keys.
+ * @param newEncKeyResolver resolver for EncryptedKey elements
+ * @param newRecipients valid recipients of EncryptedKey elements
+ */
+ public Decrypter(@Nullable final KeyInfoCredentialResolver newResolver,
+ @Nullable final KeyInfoCredentialResolver newKEKResolver,
+ @Nullable final EncryptedKeyResolver newEncKeyResolver,
+ @Nullable final Set<String> newRecipients) {
+
+ this(newResolver, newKEKResolver, newEncKeyResolver, newRecipients, null, null);
}
/**
@@ -269,12 +289,33 @@ public class Decrypter {
@Nullable final EncryptedKeyResolver newEncKeyResolver,
@Nullable final Collection<String> includeAlgos,
@Nullable final Collection<String> excludeAlgos) {
+
+ this(newResolver, newKEKResolver, newEncKeyResolver, null, includeAlgos, excludeAlgos);
+ }
+
+ /**
+ * Constructor.
+ *
+ * @param newResolver resolver for data encryption keys.
+ * @param newKEKResolver resolver for key encryption keys.
+ * @param newEncKeyResolver resolver for EncryptedKey elements
+ * @param newRecipients valid recipients of EncryptedKey elements
+ * @param includeAlgos collection of included algorithm URIs
+ * @param excludeAlgos collection of excluded algorithm URIs
+ */
+ public Decrypter(@Nullable final KeyInfoCredentialResolver newResolver,
+ @Nullable final KeyInfoCredentialResolver newKEKResolver,
+ @Nullable final EncryptedKeyResolver newEncKeyResolver,
+ @Nullable final Set<String> newRecipients,
+ @Nullable final Collection<String> includeAlgos,
+ @Nullable final Collection<String> excludeAlgos) {
this();
resolver = newResolver;
kekResolver = newKEKResolver;
encKeyResolver = newEncKeyResolver;
+ recipients = newRecipients;
includedAlgorithmURIs = includeAlgos;
excludedAlgorithmURIs = excludeAlgos;
}
@@ -838,7 +879,7 @@ public class Decrypter {
@Nullable private DocumentFragment decryptUsingResolvedEncryptedKey(@Nonnull final EncryptedData encryptedData,
@Nonnull final String algorithm) {
if (encKeyResolver != null) {
- for (final EncryptedKey encryptedKey : encKeyResolver.resolve(encryptedData)) {
+ for (final EncryptedKey encryptedKey : encKeyResolver.resolve(encryptedData, recipients)) {
try {
assert encryptedKey != null;
final Key decryptedKey = decryptKey(encryptedKey, algorithm);
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/EncryptedKeyResolver.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/EncryptedKeyResolver.java
index f94b757e2..f9358dac5 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/EncryptedKeyResolver.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/EncryptedKeyResolver.java
@@ -20,12 +20,14 @@ package org.opensaml.xmlsec.encryption.support;
import java.util.Set;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.xmlsec.encryption.EncryptedData;
import org.opensaml.xmlsec.encryption.EncryptedKey;
import net.shibboleth.shared.annotation.constraint.NotLive;
import net.shibboleth.shared.annotation.constraint.Unmodifiable;
+import net.shibboleth.shared.collection.CollectionSupport;
/**
* Interface for resolving {@link EncryptedKey} elements based on a particular
@@ -43,14 +45,28 @@ public interface EncryptedKeyResolver {
* @param encryptedData the EncryptedData element context in which to resolve
* @return an iterable of EncryptedKey elements
*/
- @Nonnull Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData);
+ default @Nonnull Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData) {
+ return resolve(encryptedData, CollectionSupport.emptySet());
+ }
+ /**
+ * Resolve the EncryptedKey elements containing the data encryption key used to
+ * encrypt the specified EncryptedData element.
+ *
+ * @param encryptedData the EncryptedData element context in which to resolve
+ * @param recipients the recipients to use during resolution
+ * @return an iterable of EncryptedKey elements
+ */
+ @Nonnull Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData,
+ @Nullable final Set<String> recipients);
+
/**
* Get the set of recipient criteria used by this resolver, and against which a candidate
* EncryptedKey's Recipient attribute is evaluated.
*
* @return the collection of recipient criteria
*/
+ @Deprecated
@Nonnull @Unmodifiable @NotLive Set<String> getRecipients();
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/InlineEncryptedKeyResolver.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/InlineEncryptedKeyResolver.java
index c54b0b7a5..0eacbe0bf 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/InlineEncryptedKeyResolver.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/InlineEncryptedKeyResolver.java
@@ -1,5 +1,6 @@
/*
* Licensed to the University Corporation for Advanced Internet Development,
+
* Inc. (UCAID) under one or more contributor license agreements. See the
* NOTICE file distributed with this work for additional information regarding
* copyright ownership. The UCAID licenses this file to You under the Apache
@@ -20,6 +21,7 @@ package org.opensaml.xmlsec.encryption.support;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -47,6 +49,7 @@ public class InlineEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
*
* @param recipients the set of recipients
*/
+ @Deprecated
public InlineEncryptedKeyResolver(@Nullable final Set<String> recipients) {
super(recipients);
}
@@ -56,28 +59,24 @@ public class InlineEncryptedKeyResolver extends AbstractEncryptedKeyResolver {
*
* @param recipient the recipient
*/
+ @Deprecated
public InlineEncryptedKeyResolver(@Nullable final String recipient) {
this(recipient != null ? CollectionSupport.singleton(recipient) : null);
}
/** {@inheritDoc} */
- @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData) {
+ @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData,
+ @Nullable final Set<String> recipients) {
Constraint.isNotNull(encryptedData, "EncryptedData cannot be null");
- final List<EncryptedKey> resolvedEncKeys = new ArrayList<>();
-
final KeyInfo keyInfo = encryptedData.getKeyInfo();
if (keyInfo == null) {
- return resolvedEncKeys;
- }
-
- for (final EncryptedKey encKey : keyInfo.getEncryptedKeys()) {
- if (matchRecipient(encKey.getRecipient())) {
- resolvedEncKeys.add(encKey);
- }
+ return CollectionSupport.emptyList();
}
- return resolvedEncKeys;
+ return keyInfo.getEncryptedKeys().stream()
+ .filter(ek -> matchRecipient(ek.getRecipient(), getEffectiveRecipients(recipients)))
+ .collect(CollectionSupport.nonnullCollector(Collectors.toUnmodifiableList())).get();
}
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleKeyInfoReferenceEncryptedKeyResolver.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleKeyInfoReferenceEncryptedKeyResolver.java
index 190ae0ac6..7ab6f6375 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleKeyInfoReferenceEncryptedKeyResolver.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleKeyInfoReferenceEncryptedKeyResolver.java
@@ -31,6 +31,9 @@ import org.opensaml.xmlsec.signature.KeyInfo;
import org.opensaml.xmlsec.signature.KeyInfoReference;
import org.slf4j.Logger;
+import net.shibboleth.shared.annotation.constraint.NonnullElements;
+import net.shibboleth.shared.annotation.constraint.NotLive;
+import net.shibboleth.shared.annotation.constraint.Unmodifiable;
import net.shibboleth.shared.collection.CollectionSupport;
import net.shibboleth.shared.logic.Constraint;
import net.shibboleth.shared.primitive.LoggerFactory;
@@ -63,6 +66,7 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolver extends AbstractEncrypte
*
* @param recipients the set of recipients
*/
+ @Deprecated
public SimpleKeyInfoReferenceEncryptedKeyResolver(@Nullable final Set<String> recipients) {
super(recipients);
depthLimit = 5;
@@ -73,6 +77,7 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolver extends AbstractEncrypte
*
* @param recipient the recipient
*/
+ @Deprecated
public SimpleKeyInfoReferenceEncryptedKeyResolver(@Nullable final String recipient) {
this(recipient != null ? CollectionSupport.singleton(recipient) : null);
}
@@ -97,10 +102,13 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolver extends AbstractEncrypte
/** {@inheritDoc} */
@Override
- @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData) {
+ @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData,
+ @Nullable final Set<String> recipients) {
Constraint.isNotNull(encryptedData, "EncryptedData cannot be null");
- return resolveKeyInfo(encryptedData.getKeyInfo(), depthLimit);
+ final Set<String> validRecipients = getEffectiveRecipients(recipients);
+
+ return resolveKeyInfo(encryptedData.getKeyInfo(), depthLimit, validRecipients);
}
/**
@@ -108,9 +116,12 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolver extends AbstractEncrypte
*
* @param keyInfo KeyInfo to process
* @param limit depth of references to follow
+ * @param validRecipients recipients to consider valid for matching purposes.
* @return encrypted keys
*/
- @Nonnull protected Iterable<EncryptedKey> resolveKeyInfo(@Nullable final KeyInfo keyInfo, final int limit) {
+ @Nonnull protected Iterable<EncryptedKey> resolveKeyInfo(@Nullable final KeyInfo keyInfo, final int limit,
+ @Nonnull @NonnullElements @Unmodifiable @NotLive final Set<String> validRecipients) {
+
final List<EncryptedKey> resolvedEncKeys = new ArrayList<>();
if (keyInfo == null) {
@@ -121,7 +132,7 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolver extends AbstractEncrypte
// After that, we always start by looking inline.
if (limit < depthLimit) {
for (final EncryptedKey encKey : keyInfo.getEncryptedKeys()) {
- if (matchRecipient(encKey.getRecipient())) {
+ if (matchRecipient(encKey.getRecipient(), validRecipients)) {
resolvedEncKeys.add(encKey);
}
}
@@ -132,7 +143,7 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolver extends AbstractEncrypte
} else {
for (final KeyInfoReference ref : keyInfo.getKeyInfoReferences()) {
assert ref != null;
- for (final EncryptedKey encKey : resolveKeyInfo(dereferenceURI(ref), limit-1)) {
+ for (final EncryptedKey encKey : resolveKeyInfo(dereferenceURI(ref), limit-1, validRecipients)) {
resolvedEncKeys.add(encKey);
}
}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleRetrievalMethodEncryptedKeyResolver.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleRetrievalMethodEncryptedKeyResolver.java
index 48b989719..d9de96e65 100644
--- a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleRetrievalMethodEncryptedKeyResolver.java
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/encryption/support/SimpleRetrievalMethodEncryptedKeyResolver.java
@@ -61,6 +61,7 @@ public class SimpleRetrievalMethodEncryptedKeyResolver extends AbstractEncrypted
*
* @param recipients the set of recipients
*/
+ @Deprecated
public SimpleRetrievalMethodEncryptedKeyResolver(@Nullable final Set<String> recipients) {
super(recipients);
}
@@ -70,19 +71,21 @@ public class SimpleRetrievalMethodEncryptedKeyResolver extends AbstractEncrypted
*
* @param recipient the recipient
*/
+ @Deprecated
public SimpleRetrievalMethodEncryptedKeyResolver(@Nullable final String recipient) {
this(recipient != null ? CollectionSupport.singleton(recipient) : null);
}
/** {@inheritDoc} */
- @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData) {
+ @Nonnull public Iterable<EncryptedKey> resolve(@Nonnull final EncryptedData encryptedData,
+ @Nullable final Set<String> recipients) {
Constraint.isNotNull(encryptedData, "EncryptedData cannot be null");
final List<EncryptedKey> resolvedEncKeys = new ArrayList<>();
final KeyInfo keyInfo = encryptedData.getKeyInfo();
if (keyInfo == null) {
- return resolvedEncKeys;
+ return CollectionSupport.emptyList();
}
for (final RetrievalMethod rm : keyInfo.getRetrievalMethods()) {
@@ -92,11 +95,13 @@ public class SimpleRetrievalMethodEncryptedKeyResolver extends AbstractEncrypted
log.warn("EncryptedKey RetrievalMethod has transforms, cannot process");
continue;
}
+
+ final Set<String> validRecipients = getEffectiveRecipients(recipients);
final EncryptedKey encKey = dereferenceURI(rm);
if (encKey == null) {
continue;
- } else if (matchRecipient(encKey.getRecipient())) {
+ } else if (matchRecipient(encKey.getRecipient(), validRecipients)) {
resolvedEncKeys.add(encKey);
}
}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionConfiguration.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionConfiguration.java
index c7baac153..1841b0165 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionConfiguration.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionConfiguration.java
@@ -17,6 +17,8 @@
package org.opensaml.xmlsec.impl;
+import java.util.Set;
+
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -38,6 +40,9 @@ public class BasicDecryptionConfiguration extends BasicAlgorithmPolicyConfigurat
/** The EncryptedKey resolver. */
@Nullable private EncryptedKeyResolver encryptedKeyResolver;
+
+ /** The set of recipients against which to evaluate candidate EncryptedKey elements. */
+ @Nullable private Set<String> recipients;
//TODO chaining to parent config instance on getters? or use a wrapping proxy, etc?
@@ -109,4 +114,22 @@ public class BasicDecryptionConfiguration extends BasicAlgorithmPolicyConfigurat
return this;
}
+ /**
+ * Get the set of recipients against which to evaluate candidate EncryptedKey elements.
+ *
+ * @return the recipients
+ */
+ public @Nullable Set<String> getRecipients() {
+ return recipients;
+ }
+
+ /**
+ * Set the set of recipients against which to evaluate candidate EncryptedKey elements.
+ *
+ * @param newRecipients the recipients
+ */
+ public void setRecipients(@Nullable Set<String> newRecipients) {
+ recipients = newRecipients;
+ }
+
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolver.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolver.java
index 8cefc23f2..2f51f4335 100644
--- a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolver.java
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolver.java
@@ -17,6 +17,9 @@
package org.opensaml.xmlsec.impl;
+import java.util.HashSet;
+import java.util.Set;
+
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -30,6 +33,7 @@ import org.opensaml.xmlsec.DecryptionConfiguration;
import org.opensaml.xmlsec.DecryptionParameters;
import org.opensaml.xmlsec.DecryptionParametersResolver;
import org.opensaml.xmlsec.criterion.DecryptionConfigurationCriterion;
+import org.opensaml.xmlsec.criterion.DecryptionRecipientsCriterion;
import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;
import org.slf4j.Logger;
@@ -79,6 +83,7 @@ public class BasicDecryptionParametersResolver extends AbstractSecurityParameter
params.setDataKeyInfoCredentialResolver(resolveDataKeyInfoCredentialResolver(criteria));
params.setKEKKeyInfoCredentialResolver(resolveKEKKeyInfoCredentialResolver(criteria));
params.setEncryptedKeyResolver(resolveEncryptedKeyResolver(criteria));
+ params.setRecipients(resolveRecipients(criteria));
logResult(params);
@@ -103,6 +108,8 @@ public class BasicDecryptionParametersResolver extends AbstractSecurityParameter
params.getKEKKeyInfoCredentialResolver() != null ? "present" : "null");
log.debug("\tEncryptedKeyResolver: {}",
params.getEncryptedKeyResolver() != null ? "present" : "null");
+
+ log.debug("\tRecipients: {}", params.getRecipients());
}
}
@@ -169,4 +176,31 @@ public class BasicDecryptionParametersResolver extends AbstractSecurityParameter
return null;
}
+ /**
+ * Resolve the effective set of recipients against which to evaluate candidate EncryptedKey elements.
+ *
+ * @param criteria the input criteria being evaluated
+ * @return the recipients set, or null
+ */
+ private Set<String> resolveRecipients(@Nonnull final CriteriaSet criteria) {
+ final DecryptionConfigurationCriterion configCriterion = criteria.get(DecryptionConfigurationCriterion.class);
+ assert configCriterion != null;
+
+ final Set<String> recipients = new HashSet<>();
+
+ for (final DecryptionConfiguration config : configCriterion.getConfigurations()) {
+ if (config.getRecipients() != null) {
+ recipients.addAll(config.getRecipients());
+ break;
+ }
+ }
+
+ final DecryptionRecipientsCriterion recipientsCriterion = criteria.get(DecryptionRecipientsCriterion.class);
+ if (recipientsCriterion != null) {
+ recipients.addAll(recipientsCriterion.getRecipients());
+ }
+
+ return recipients.isEmpty() ? null : recipients;
+ }
+
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/ChainingEncryptedKeyResolverTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/ChainingEncryptedKeyResolverTest.java
index 98b2c7bd2..8a4ee5ac7 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/ChainingEncryptedKeyResolverTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/ChainingEncryptedKeyResolverTest.java
@@ -22,8 +22,11 @@ import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.core.testing.XMLObjectBaseTestCase;
import org.opensaml.core.xml.XMLObject;
@@ -39,6 +42,8 @@ import org.testng.Assert;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
+import net.shibboleth.shared.collection.CollectionSupport;
+
/**
* Test the encrypted key resolver which dereferences RetrievalMethods.
*/
@@ -84,7 +89,7 @@ public class ChainingEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
resolver = new ChainingEncryptedKeyResolver(new ArrayList<EncryptedKeyResolver>());
- generateList(encData, resolver);
+ generateList(encData, resolver, null);
}
/** One recipient specified to resolver, EncryptedKey in instance inline. */
@@ -108,9 +113,9 @@ public class ChainingEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
recipients.add("foo");
- resolver = new ChainingEncryptedKeyResolver(resolverChain, recipients);
+ resolver = new ChainingEncryptedKeyResolver(resolverChain);
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, recipients);
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -137,9 +142,9 @@ public class ChainingEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
recipients.add("foo");
- resolver = new ChainingEncryptedKeyResolver(resolverChain, recipients);
+ resolver = new ChainingEncryptedKeyResolver(resolverChain);
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, recipients);
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -166,9 +171,9 @@ public class ChainingEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
recipients.add("foo");
- resolver = new ChainingEncryptedKeyResolver(resolverChain, recipients);
+ resolver = new ChainingEncryptedKeyResolver(resolverChain);
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, recipients);
Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -197,9 +202,42 @@ public class ChainingEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
recipients.add("foo");
recipients.add("baz");
- resolver = new ChainingEncryptedKeyResolver(resolverChain, recipients);
+ resolver = new ChainingEncryptedKeyResolver(resolverChain);
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, recipients);
+ Assert.assertEquals(resolved.size(), 4, "Incorrect number of resolved EncryptedKeys found");
+
+ Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(1) == allKeys.get(2), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(2) == allKeys.get(3), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(3) == allKeys.get(5), "Unexpected EncryptedKey instance found");
+ }
+
+ /** Multi recipient specified to resolver via ctor and method args. */
+ @Test
+ @SuppressWarnings("deprecation")
+ public void testMultiRecipientsCtorAndArgs() {
+ String filename = "/org/opensaml/xmlsec/encryption/support/ChainingEncryptedKeyResolverMultiple.xml";
+ SignableSimpleXMLObject sxo = (SignableSimpleXMLObject) unmarshallElement(filename);
+ assert sxo != null;
+ Assert.assertNotNull(sxo.getSimpleXMLObjects().get(0));
+ Assert.assertNotNull(sxo.getSimpleXMLObjects().get(0).getEncryptedData());
+
+ final EncryptedData encData = sxo.getSimpleXMLObjects().get(0).getEncryptedData();
+ assert encData != null;
+ final KeyInfo keyInfo = encData.getKeyInfo();
+ assert keyInfo != null;
+ Assert.assertFalse(keyInfo.getEncryptedKeys().isEmpty());
+ Assert.assertFalse(keyInfo.getRetrievalMethods().isEmpty());
+
+ List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
+ Assert.assertFalse(allKeys.isEmpty());
+
+ recipients.add("baz");
+
+ resolver = new ChainingEncryptedKeyResolver(resolverChain, CollectionSupport.singleton("foo"));
+
+ List<EncryptedKey> resolved = generateList(encData, resolver, recipients);
Assert.assertEquals(resolved.size(), 4, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -229,20 +267,20 @@ public class ChainingEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
}
return allKeys;
}
-
+
/**
* Resolve EncryptedKeys and put them in an ordered list.
*
* @param encData the EncryptedData context
* @param ekResolver the resolver to test
+ * @param recipients the valid recipients for resolution
* @return list of resolved EncryptedKeys
*/
- private List<EncryptedKey> generateList(EncryptedData encData, EncryptedKeyResolver ekResolver) {
- List<EncryptedKey> resolved = new ArrayList<>();
- for (EncryptedKey encKey : ekResolver.resolve(encData)) {
- resolved.add(encKey);
- }
- return resolved;
+ @Nonnull private List<EncryptedKey> generateList(@Nonnull final EncryptedData encData,
+ @Nonnull final EncryptedKeyResolver ekResolver, @Nullable final Set<String> recipients) {
+
+ return StreamSupport.stream(ekResolver.resolve(encData, recipients).spliterator(), false)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
}
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/InlineEncryptedKeyResolverTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/InlineEncryptedKeyResolverTest.java
index c101aac6f..900367949 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/InlineEncryptedKeyResolverTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/InlineEncryptedKeyResolverTest.java
@@ -17,16 +17,13 @@
package org.opensaml.xmlsec.encryption.support.tests;
-import org.testng.annotations.Test;
-
-import net.shibboleth.shared.collection.CollectionSupport;
-
-import org.testng.Assert;
-
-import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.core.testing.XMLObjectBaseTestCase;
import org.opensaml.xmlsec.encryption.EncryptedData;
@@ -34,6 +31,10 @@ import org.opensaml.xmlsec.encryption.EncryptedKey;
import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver;
import org.opensaml.xmlsec.signature.KeyInfo;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.collection.CollectionSupport;
/**
* Test the inline encrypted key resolver.
@@ -58,7 +59,7 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
resolver = new InlineEncryptedKeyResolver();
- final List<EncryptedKey> resolved = generateList(encData, resolver);
+ final List<EncryptedKey> resolved = generateList(encData, resolver, null);
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -76,9 +77,9 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
final List<EncryptedKey> allKeys = keyInfo.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new InlineEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new InlineEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -96,9 +97,9 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
final List<EncryptedKey> allKeys = keyInfo.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new InlineEncryptedKeyResolver(CollectionSupport.singleton("bar"));
+ resolver = new InlineEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("bar"));
Assert.assertEquals(resolved.size(), 0, "Incorrect number of resolved EncryptedKeys found");
}
@@ -116,7 +117,7 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
resolver = new InlineEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, null);
Assert.assertEquals(resolved.size(), 4, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -138,9 +139,9 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
final List<EncryptedKey> allKeys = keyInfo.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new InlineEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new InlineEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -159,9 +160,9 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
final List<EncryptedKey> allKeys = keyInfo.getEncryptedKeys();
Assert.assertFalse(allKeys.isEmpty());
- resolver = new InlineEncryptedKeyResolver(CollectionSupport.setOf("foo", "baz"));
+ resolver = new InlineEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.setOf("foo", "baz"));
Assert.assertEquals(resolved.size(), 3, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -169,20 +170,42 @@ public class InlineEncryptedKeyResolverTest extends XMLObjectBaseTestCase {
Assert.assertTrue(resolved.get(2) == allKeys.get(3), "Unexpected EncryptedKey instance found");
}
+ /** Multi recipient specified to resolver via ctor and method args. */
+ @Test
+ @SuppressWarnings("deprecation")
+ public void testMultiRecipientsCtorAndArgs() {
+ final String filename = "/org/opensaml/xmlsec/encryption/support/InlineEncryptedKeyResolverMultiple.xml";
+ final EncryptedData encData = (EncryptedData) unmarshallElement(filename);
+ assert encData != null;
+
+ final KeyInfo keyInfo = encData.getKeyInfo();
+ assert keyInfo != null;
+ final List<EncryptedKey> allKeys = keyInfo.getEncryptedKeys();
+ Assert.assertFalse(allKeys.isEmpty());
+
+ resolver = new InlineEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("baz"));
+ Assert.assertEquals(resolved.size(), 3, "Incorrect number of resolved EncryptedKeys found");
+
+ Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(1) == allKeys.get(2), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(2) == allKeys.get(3), "Unexpected EncryptedKey instance found");
+ }
+
/**
* Resolve EncryptedKeys and put them in an ordered list.
*
* @param encData the EncryptedData context
* @param ekResolver the resolver to test
+ * @param recipients the valid recipients for resolution
* @return list of resolved EncryptedKeys
*/
@Nonnull private List<EncryptedKey> generateList(@Nonnull final EncryptedData encData,
- @Nonnull final EncryptedKeyResolver ekResolver) {
- List<EncryptedKey> resolved = new ArrayList<>();
- for (EncryptedKey encKey : ekResolver.resolve(encData)) {
- resolved.add(encKey);
- }
- return resolved;
+ @Nonnull final EncryptedKeyResolver ekResolver, @Nullable final Set<String> recipients) {
+
+ return StreamSupport.stream(ekResolver.resolve(encData, recipients).spliterator(), false)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
}
}
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleKeyInfoReferenceEncryptedKeyResolverTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleKeyInfoReferenceEncryptedKeyResolverTest.java
index 6da63d532..ecbebee51 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleKeyInfoReferenceEncryptedKeyResolverTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleKeyInfoReferenceEncryptedKeyResolverTest.java
@@ -19,8 +19,12 @@ package org.opensaml.xmlsec.encryption.support.tests;
import java.util.ArrayList;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.core.testing.XMLObjectBaseTestCase;
import org.opensaml.core.xml.XMLObject;
@@ -64,7 +68,7 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolverTest extends XMLObjectBas
resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, null);
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -88,9 +92,9 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolverTest extends XMLObjectBas
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -114,9 +118,9 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolverTest extends XMLObjectBas
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -143,9 +147,37 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolverTest extends XMLObjectBas
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver(CollectionSupport.setOf("foo", "baz"));
+ resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.setOf("foo", "baz"));
+ Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
+
+ Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(1) == allKeys.get(2), "Unexpected EncryptedKey instance found");
+ }
+
+ /** Multi recipient specified to resolver via ctor and method args. */
+ @Test
+ @SuppressWarnings("deprecation")
+ public void testMultiRecipientsCtorAndArgs() {
+ final String filename = "/org/opensaml/xmlsec/encryption/support/SimpleKeyInfoReferenceEncryptedKeyResolverMultiple.xml";
+ final SignableSimpleXMLObject sxo = (SignableSimpleXMLObject) unmarshallElement(filename);
+ assert sxo != null;
+ Assert.assertNotNull(sxo.getSimpleXMLObjects().get(0));
+ Assert.assertNotNull(sxo.getSimpleXMLObjects().get(0).getEncryptedData());
+
+ final EncryptedData encData = sxo.getSimpleXMLObjects().get(0).getEncryptedData();
+ assert encData != null;
+ final KeyInfo keyInfo = encData.getKeyInfo();
+ assert keyInfo != null;
+ Assert.assertFalse(keyInfo.getKeyInfoReferences().isEmpty());
+
+ List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
+ Assert.assertFalse(allKeys.isEmpty());
+
+ resolver = new SimpleKeyInfoReferenceEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("baz"));
Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -167,21 +199,20 @@ public class SimpleKeyInfoReferenceEncryptedKeyResolverTest extends XMLObjectBas
}
return allKeys;
}
-
+
/**
* Resolve EncryptedKeys and put them in an ordered list.
*
* @param encData the EncryptedData context
* @param ekResolver the resolver to test
+ * @param recipients the valid recipients for resolution
* @return list of resolved EncryptedKeys
*/
@Nonnull private List<EncryptedKey> generateList(@Nonnull final EncryptedData encData,
- @Nonnull final EncryptedKeyResolver ekResolver) {
- List<EncryptedKey> resolved = new ArrayList<>();
- for (EncryptedKey encKey : ekResolver.resolve(encData)) {
- resolved.add(encKey);
- }
- return resolved;
+ @Nonnull final EncryptedKeyResolver ekResolver, @Nullable final Set<String> recipients) {
+
+ return StreamSupport.stream(ekResolver.resolve(encData, recipients).spliterator(), false)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
}
}
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleRetrievalMethodEncryptedKeyResolverTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleRetrievalMethodEncryptedKeyResolverTest.java
index ba12d2209..a0d18a915 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleRetrievalMethodEncryptedKeyResolverTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/encryption/support/tests/SimpleRetrievalMethodEncryptedKeyResolverTest.java
@@ -17,17 +17,14 @@
package org.opensaml.xmlsec.encryption.support.tests;
-import org.testng.annotations.Test;
-
-import net.shibboleth.shared.collection.CollectionSupport;
-
-import org.testng.Assert;
-
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
import org.opensaml.core.testing.XMLObjectBaseTestCase;
import org.opensaml.core.xml.XMLObject;
@@ -37,6 +34,10 @@ import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
import org.opensaml.xmlsec.encryption.support.SimpleRetrievalMethodEncryptedKeyResolver;
import org.opensaml.xmlsec.mock.SignableSimpleXMLObject;
import org.opensaml.xmlsec.signature.KeyInfo;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.shared.collection.CollectionSupport;
/**
* Test the encrypted key resolver which dereferences RetrievalMethods.
@@ -66,7 +67,7 @@ public class SimpleRetrievalMethodEncryptedKeyResolverTest extends XMLObjectBase
resolver = new SimpleRetrievalMethodEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, null);
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -90,9 +91,9 @@ public class SimpleRetrievalMethodEncryptedKeyResolverTest extends XMLObjectBase
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleRetrievalMethodEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new SimpleRetrievalMethodEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -117,9 +118,9 @@ public class SimpleRetrievalMethodEncryptedKeyResolverTest extends XMLObjectBase
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleRetrievalMethodEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new SimpleRetrievalMethodEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 0, "Incorrect number of resolved EncryptedKeys found");
}
@@ -142,9 +143,9 @@ public class SimpleRetrievalMethodEncryptedKeyResolverTest extends XMLObjectBase
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleRetrievalMethodEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+ resolver = new SimpleRetrievalMethodEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("foo"));
Assert.assertEquals(resolved.size(), 1, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -169,9 +170,37 @@ public class SimpleRetrievalMethodEncryptedKeyResolverTest extends XMLObjectBase
List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
Assert.assertFalse(allKeys.isEmpty());
- resolver = new SimpleRetrievalMethodEncryptedKeyResolver(CollectionSupport.setOf("foo", "baz"));
+ resolver = new SimpleRetrievalMethodEncryptedKeyResolver();
- List<EncryptedKey> resolved = generateList(encData, resolver);
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.setOf("foo", "baz"));
+ Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
+
+ Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
+ Assert.assertTrue(resolved.get(1) == allKeys.get(2), "Unexpected EncryptedKey instance found");
+ }
+
+ /** Multi recipient specified to resolver via ctor and method args. */
+ @Test
+ @SuppressWarnings("deprecation")
+ public void testMultiRecipientsCtorAndArgs() {
+ String filename = "/org/opensaml/xmlsec/encryption/support/SimpleRetrievalMethodEncryptedKeyResolverMultiple.xml";
+ final SignableSimpleXMLObject sxo = (SignableSimpleXMLObject) unmarshallElement(filename);
+ assert sxo != null;
+ Assert.assertNotNull(sxo.getSimpleXMLObjects().get(0));
+ Assert.assertNotNull(sxo.getSimpleXMLObjects().get(0).getEncryptedData());
+
+ final EncryptedData encData = sxo.getSimpleXMLObjects().get(0).getEncryptedData();
+ assert encData != null;
+ final KeyInfo keyInfo = encData.getKeyInfo();
+ assert keyInfo != null;
+ Assert.assertFalse(keyInfo.getRetrievalMethods().isEmpty());
+
+ List<EncryptedKey> allKeys = getEncryptedKeys(sxo);
+ Assert.assertFalse(allKeys.isEmpty());
+
+ resolver = new SimpleRetrievalMethodEncryptedKeyResolver(CollectionSupport.singleton("foo"));
+
+ List<EncryptedKey> resolved = generateList(encData, resolver, CollectionSupport.singleton("baz"));
Assert.assertEquals(resolved.size(), 2, "Incorrect number of resolved EncryptedKeys found");
Assert.assertTrue(resolved.get(0) == allKeys.get(0), "Unexpected EncryptedKey instance found");
@@ -193,21 +222,20 @@ public class SimpleRetrievalMethodEncryptedKeyResolverTest extends XMLObjectBase
}
return allKeys;
}
-
+
/**
* Resolve EncryptedKeys and put them in an ordered list.
*
* @param encData the EncryptedData context
* @param ekResolver the resolver to test
+ * @param recipients the valid recipients for resolution
* @return list of resolved EncryptedKeys
*/
@Nonnull private List<EncryptedKey> generateList(@Nonnull final EncryptedData encData,
- @Nonnull final EncryptedKeyResolver ekResolver) {
- List<EncryptedKey> resolved = new ArrayList<>();
- for (EncryptedKey encKey : ekResolver.resolve(encData)) {
- resolved.add(encKey);
- }
- return resolved;
+ @Nonnull final EncryptedKeyResolver ekResolver, @Nullable final Set<String> recipients) {
+
+ return StreamSupport.stream(ekResolver.resolve(encData, recipients).spliterator(), false)
+ .collect(CollectionSupport.nonnullCollector(Collectors.toList())).get();
}
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolverTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolverTest.java
index cdc803ab2..efd0be190 100644
--- a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolverTest.java
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/impl/BasicDecryptionParametersResolverTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertNull;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
+import java.util.Set;
import net.shibboleth.shared.logic.ConstraintViolationException;
import net.shibboleth.shared.resolver.CriteriaSet;
@@ -29,6 +30,7 @@ import net.shibboleth.shared.resolver.ResolverException;
import org.opensaml.xmlsec.DecryptionParameters;
import org.opensaml.xmlsec.criterion.DecryptionConfigurationCriterion;
+import org.opensaml.xmlsec.criterion.DecryptionRecipientsCriterion;
import org.opensaml.xmlsec.encryption.support.EncryptedKeyResolver;
import org.opensaml.xmlsec.encryption.support.InlineEncryptedKeyResolver;
import org.opensaml.xmlsec.keyinfo.KeyInfoCredentialResolver;
@@ -153,6 +155,57 @@ public class BasicDecryptionParametersResolverTest {
Assert.assertTrue(encKeyResolver == controlEncKeyResolver3);
}
+ @Test
+ public void testNoRecipients() throws ResolverException {
+ final DecryptionParameters params = resolver.resolveSingle(criteriaSet);
+ assert params != null;
+
+ Assert.assertNull(params.getRecipients());
+ }
+
+ @Test
+ public void testRecipientsFromConfig() throws ResolverException {
+ config1.setRecipients(Set.of("A", "B", "C"));
+
+ final DecryptionParameters params = resolver.resolveSingle(criteriaSet);
+ assert params != null;
+
+ final Set<String> recipients = params.getRecipients();
+ assert recipients != null;
+
+ Assert.assertNotNull(recipients);
+ Assert.assertTrue(recipients.equals(Set.of("A", "B", "C")));
+ }
+
+ @Test
+ public void testRecipientsFromCriterion() throws ResolverException {
+ criteriaSet.add(new DecryptionRecipientsCriterion(Set.of("X", "Y", "Z")));
+
+ final DecryptionParameters params = resolver.resolveSingle(criteriaSet);
+ assert params != null;
+
+ final Set<String> recipients = params.getRecipients();
+ assert recipients != null;
+
+ Assert.assertNotNull(recipients);
+ Assert.assertTrue(recipients.equals(Set.of("X", "Y", "Z")));
+ }
+
+ @Test
+ public void testRecipientsFromConfigAndCriterion() throws ResolverException {
+ config2.setRecipients(Set.of("A", "B", "C"));
+ criteriaSet.add(new DecryptionRecipientsCriterion(Set.of("X", "Y", "Z")));
+
+ final DecryptionParameters params = resolver.resolveSingle(criteriaSet);
+ assert params != null;
+
+ final Set<String> recipients = params.getRecipients();
+ assert recipients != null;
+
+ Assert.assertNotNull(recipients);
+ Assert.assertTrue(recipients.equals(Set.of("A", "B", "C", "X", "Y", "Z")));
+ }
+
@Test
public void testResolve() throws ResolverException {
config1.setExcludedAlgorithms(List.of("foo", "bar"));
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list