[java-opensaml] 04/15: Basic framework classes for key agreement processing, incl ECDH impl.

Brent Putman putmanb at georgetown.edu
Thu Jan 21 21:33:24 UTC 2021


This is an automated email from the git hooks/post-receive script.

putmanb pushed a commit to branch dev/OSJ-82
in repository java-opensaml.

View the commit online:
http://git.shibboleth.net/view/?p=java-opensaml.git;a=commit;h=fc17204e22eee1f75512d341f512ad2b34fe86ab

commit fc17204e22eee1f75512d341f512ad2b34fe86ab
Author: Brent Putman <putmanb at georgetown.edu>
AuthorDate: Fri Dec 18 14:11:15 2020 -0500

    Basic framework classes for key agreement processing, incl ECDH impl.
---
 .../xmlsec/agreement/KeyAgreementCredential.java   |  62 ++++++++++
 .../xmlsec/agreement/KeyAgreementException.java    |  67 +++++++++++
 .../xmlsec/agreement/KeyAgreementParameter.java    |  25 ++++
 .../xmlsec/agreement/KeyAgreementParameters.java   |  27 +++++
 .../xmlsec/agreement/KeyAgreementProcessor.java    |  52 ++++++++
 .../XMLExpressableKeyAgreementParameter.java       |  43 +++++++
 .../opensaml/xmlsec/agreement/package-info.java    |  19 +++
 .../opensaml/xmlsec/derivation/KeyDerivation.java  |  54 +++++++++
 .../xmlsec/derivation/KeyDerivationException.java  |  67 +++++++++++
 .../opensaml/xmlsec/derivation/package-info.java   |  19 +++
 .../AbstractDerivationKeyAgreementProcessor.java   |  57 +++++++++
 .../impl/AbstractKeyAgreementProcessor.java        | 116 ++++++++++++++++++
 .../impl/BasicKeyAgreementCredential.java          |  86 +++++++++++++
 .../agreement/impl/ECDHKeyAgreementProcessor.java  |  89 ++++++++++++++
 .../opensaml/xmlsec/agreement/impl/KANonce.java    |  65 ++++++++++
 .../xmlsec/agreement/impl/package-info.java        |  19 +++
 .../opensaml/xmlsec/derivation/impl/ConcatKDF.java |  66 ++++++++++
 .../opensaml/xmlsec/derivation/impl/PBKDF2.java    |  66 ++++++++++
 .../xmlsec/derivation/impl/package-info.java       |  19 +++
 .../impl/ECDHKeyAgreementProcessorTest.java        | 133 +++++++++++++++++++++
 .../xmlsec/agreement/impl/KANonceTest.java         |  51 ++++++++
 .../xmlsec/derivation/impl/MockKeyDerivation.java  |  58 +++++++++
 22 files changed, 1260 insertions(+)

diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementCredential.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementCredential.java
new file mode 100644
index 000000000..b81928a7f
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementCredential.java
@@ -0,0 +1,62 @@
+/*
+ * 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.agreement;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.credential.Credential;
+
+/**
+ * An entity credential which represents the result of a key agreement operation.
+ * 
+ * <p>
+ * This will typically contain a secret key only, and no public or private key.  The information available
+ * via this type's interface describes how the secret key was produced.
+ * </p>
+ */
+public interface KeyAgreementCredential extends Credential {
+    
+    /**
+     * The key agreement algorithm URI used.
+     * 
+     * @return the algorithm
+     */
+    @Nonnull public String getAlgorithm();
+    
+    /**
+     * The credential holding the originator key material.
+     * 
+     * @return the originator credential
+     */
+    @Nonnull public Credential getOriginatorCredential();
+    
+    /**
+     * The credential holding the recipient key material.
+     * 
+     * @return the recipient credential
+     */
+    @Nonnull public Credential getRecipientCredential();
+    
+    /**
+     * The parameters to the key agreement operation.
+     * 
+     * @return the parameters
+     */
+    @Nonnull public KeyAgreementParameters getParameters();
+    
+}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementException.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementException.java
new file mode 100644
index 000000000..005a65452
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementException.java
@@ -0,0 +1,67 @@
+/*
+ * 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.agreement;
+
+import javax.annotation.Nullable;
+
+/**
+ * Exception thrown when an error occurs during key agreement operations.
+ */
+public class KeyAgreementException extends Exception {
+
+    /**
+     * Serial version UID.
+     */
+    private static final long serialVersionUID = -2936335465767094633L;
+
+    /**
+     * Constructor.
+     */
+    public KeyAgreementException() {
+        super();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param message exception message
+     */
+    public KeyAgreementException(@Nullable final String message) {
+        super(message);
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param cause exception to be wrapped by this one
+     */
+    public KeyAgreementException(@Nullable final Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message exception message
+     * @param cause exception to be wrapped by this one
+     */
+    public KeyAgreementException(@Nullable final String message, @Nullable final Throwable cause) {
+        super(message, cause);
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementParameter.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementParameter.java
new file mode 100644
index 000000000..98417adb8
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementParameter.java
@@ -0,0 +1,25 @@
+/*
+ * 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.agreement;
+
+/**
+ * Marker interface for parameters to key agreement operations.
+ */
+public interface KeyAgreementParameter {
+
+}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementParameters.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementParameters.java
new file mode 100644
index 000000000..414daf45b
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementParameters.java
@@ -0,0 +1,27 @@
+/*
+ * 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.agreement;
+
+import net.shibboleth.utilities.java.support.collection.ClassIndexedSet;
+
+/**
+ * Specialized collection type for holding sets of parameters to key agreement operations.
+ */
+public class KeyAgreementParameters extends ClassIndexedSet<KeyAgreementParameter> {
+
+}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementProcessor.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementProcessor.java
new file mode 100644
index 000000000..ee51d920d
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/KeyAgreementProcessor.java
@@ -0,0 +1,52 @@
+/*
+ * 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.agreement;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.credential.Credential;
+
+/**
+ * Component which performs a key agreement operation.
+ */
+public interface KeyAgreementProcessor {
+    
+    /**
+     * The key agreement algorithm URI.
+     * 
+     * @return the algorithm
+     */
+    @Nonnull public String getAlgorithm();
+    
+    /**
+     * Perform the key agreement operation and return a new credential representing the results.
+     * 
+     * @param recipientCredential the recipient credential
+     * @param keyAlgorithm the JCA key algorithm for the derived key
+     * @param keyLength the key length for the derived key
+     * @param parameters parameters to the agreement operation
+     * 
+     * @return the agreement credential
+     * 
+     * @throws KeyAgreementException
+     */
+    @Nonnull public KeyAgreementCredential execute(@Nonnull final Credential recipientCredential,
+            @Nonnull final String keyAlgorithm, @Nonnull final Integer keyLength,
+            @Nonnull final KeyAgreementParameters parameters) throws KeyAgreementException;
+
+}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/XMLExpressableKeyAgreementParameter.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/XMLExpressableKeyAgreementParameter.java
new file mode 100644
index 000000000..632c4599c
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/XMLExpressableKeyAgreementParameter.java
@@ -0,0 +1,43 @@
+/*
+ * 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.agreement;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.xmlsec.encryption.AgreementMethod;
+import org.opensaml.xmlsec.signature.KeyInfo;
+
+/**
+ * A key agreement parameter which is capable of expressing its own {@link XMLObject} representation.
+ * 
+ * <p>
+ * Such parameter representations are typically used in populating the {@link AgreementMethod}
+ * child of a {@link KeyInfo}.
+ * </p>
+ */
+public interface XMLExpressableKeyAgreementParameter extends KeyAgreementParameter {
+    
+    /**
+     * Build an {@link XMLObject} instance representing this parameter.
+     * 
+     * @return the XML object instance
+     */
+    @Nonnull public XMLObject buildXMLObject();
+
+}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/package-info.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/package-info.java
new file mode 100644
index 000000000..73bd4ecf8
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/agreement/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** API components related to key agreement operations. */
+package org.opensaml.xmlsec.agreement;
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/KeyDerivation.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/KeyDerivation.java
new file mode 100644
index 000000000..9ef019e71
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/KeyDerivation.java
@@ -0,0 +1,54 @@
+/*
+ * 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.derivation;
+
+import javax.crypto.SecretKey;
+
+import org.opensaml.xmlsec.agreement.XMLExpressableKeyAgreementParameter;
+
+/**
+ * Component which represents a specific key derivation algorithm, and supports deriving a new {@link SecretKey}
+ * via that algorithm.
+ * 
+ * <p>
+ * Sub-types will usually contain additional configurable property inputs to the derivation operation.
+ * </p>
+ */
+public interface KeyDerivation extends XMLExpressableKeyAgreementParameter {
+    
+    /**
+     * The key derivation algorithm URI.
+     * 
+     * @return the algorithm
+     */
+    public String getAlgorithm();
+
+    /**
+     * Derive a {@link SecretKey} from the specified secret.
+     * 
+     * @param secret the input secret from which to derive the key.
+     * @param keyAlgorithm the JCA key algorithm for the derived key
+     * @param keyLength the length of for the derived key
+     * 
+     * @return the derived key
+     * 
+     * @throws KeyDerivationException
+     */
+    public SecretKey derive(byte[] secret, String keyAlgorithm, Integer keyLength) throws KeyDerivationException;
+    
+}
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/KeyDerivationException.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/KeyDerivationException.java
new file mode 100644
index 000000000..2c7b4e754
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/KeyDerivationException.java
@@ -0,0 +1,67 @@
+/*
+ * 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.derivation;
+
+import javax.annotation.Nullable;
+
+/**
+ * Exception thrown when an error occurs during key derivation operations.
+ */
+public class KeyDerivationException extends Exception {
+
+    /**
+     * Serial version UID.
+     */
+    private static final long serialVersionUID = 1745203357584881658L;
+
+    /**
+     * Constructor.
+     */
+    public KeyDerivationException() {
+        super();
+    }
+
+    /**
+     * Constructor.
+     *
+     * @param message exception message
+     */
+    public KeyDerivationException(@Nullable final String message) {
+        super(message);
+    }
+    
+    /**
+     * Constructor.
+     * 
+     * @param cause exception to be wrapped by this one
+     */
+    public KeyDerivationException(@Nullable final Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param message exception message
+     * @param cause exception to be wrapped by this one
+     */
+    public KeyDerivationException(@Nullable final String message, @Nullable final Throwable cause) {
+        super(message, cause);
+    }
+
+}
\ No newline at end of file
diff --git a/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/package-info.java b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/package-info.java
new file mode 100644
index 000000000..28e0a6f70
--- /dev/null
+++ b/opensaml-xmlsec-api/src/main/java/org/opensaml/xmlsec/derivation/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** API components related to key derivation operations. */
+package org.opensaml.xmlsec.derivation;
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/AbstractDerivationKeyAgreementProcessor.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/AbstractDerivationKeyAgreementProcessor.java
new file mode 100644
index 000000000..257f084f4
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/AbstractDerivationKeyAgreementProcessor.java
@@ -0,0 +1,57 @@
+/*
+ * 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.agreement.impl;
+
+
+import javax.annotation.Nonnull;
+import javax.crypto.SecretKey;
+
+import org.opensaml.xmlsec.agreement.KeyAgreementException;
+import org.opensaml.xmlsec.agreement.KeyAgreementParameters;
+import org.opensaml.xmlsec.agreement.KeyAgreementProcessor;
+import org.opensaml.xmlsec.derivation.KeyDerivation;
+import org.opensaml.xmlsec.derivation.KeyDerivationException;
+
+/**
+ * Abstract base class for {@link KeyAgreementProcessor} implementations which do key derivation by means of
+ * a required {@link KeyDerivation} parameter.
+ */
+public abstract class AbstractDerivationKeyAgreementProcessor extends AbstractKeyAgreementProcessor {
+
+    /** {@inheritDoc} */
+    protected SecretKey deriveSecretKey(@Nonnull final byte[] secret, @Nonnull final String keyAlgorithm,
+            @Nonnull final Integer keyLength, @Nonnull final KeyAgreementParameters parameters)
+                    throws KeyAgreementException {
+        
+        final KeyDerivation keyDerivation = parameters.stream()
+                .filter(KeyDerivation.class::isInstance)
+                .map(KeyDerivation.class::cast)
+                .findFirst()
+                .orElse(null);
+        if (keyDerivation == null) {
+            throw new KeyAgreementException("Required KeyDerivation parameter was not supplied");
+        }
+        
+        try {
+            return keyDerivation.derive(secret, keyAlgorithm, keyLength);
+        } catch (final KeyDerivationException e) {
+            throw new KeyAgreementException("Key derivation failed using supplied KeyDerivation parameter", e);
+        }
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/AbstractKeyAgreementProcessor.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/AbstractKeyAgreementProcessor.java
new file mode 100644
index 000000000..526881daa
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/AbstractKeyAgreementProcessor.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.agreement.impl;
+
+import javax.annotation.Nonnull;
+import javax.crypto.SecretKey;
+
+import org.opensaml.security.credential.Credential;
+import org.opensaml.xmlsec.agreement.KeyAgreementCredential;
+import org.opensaml.xmlsec.agreement.KeyAgreementException;
+import org.opensaml.xmlsec.agreement.KeyAgreementParameters;
+import org.opensaml.xmlsec.agreement.KeyAgreementProcessor;
+
+/**
+ * Abstract base class for {@link KeyAgreementProcessor} implementations.
+ */
+public abstract class AbstractKeyAgreementProcessor implements KeyAgreementProcessor {
+
+    /** {@inheritDoc} */
+    @Nonnull public KeyAgreementCredential execute(@Nonnull final Credential recipientCredential,
+            @Nonnull final String keyAlgorithm, @Nonnull final Integer keyLength,
+            @Nonnull final KeyAgreementParameters parameters) throws KeyAgreementException {
+        
+        final Credential originatorCredential = obtainOriginatorCredential(recipientCredential, parameters);
+        
+        final byte[] secret = generateAgreementSecret(recipientCredential, originatorCredential, parameters);
+        
+        final SecretKey derivedKey = deriveSecretKey(secret, keyAlgorithm, keyLength, parameters);
+        
+        return buildKeyAgreementCredential(derivedKey, recipientCredential, originatorCredential, parameters);
+    }
+    
+    /**
+     * Obtain an originator credential which is compatible with the given recipient credential.
+     * 
+     * @param recipientCredential the recipient credential
+     * @param parameters the key agreement parameters
+     * 
+     * @return the obtained originator credential
+     * 
+     * @throws KeyAgreementException
+     */
+    @Nonnull protected abstract Credential obtainOriginatorCredential(@Nonnull final Credential recipientCredential,
+            @Nonnull final KeyAgreementParameters parameters) throws KeyAgreementException;
+    
+    /**
+     * Generate the agreement secret according to the key algorithm and using the supplied
+     * originator and recipient credentials.
+     * 
+     * @param recipientCredential the recipient credential
+     * @param originatorCredential the originator credential
+     * @param parameters the key agreement parameters
+     * 
+     * @return the obtained originator credential
+     * 
+     * @throws KeyAgreementException
+     */
+    @Nonnull protected abstract byte[] generateAgreementSecret(@Nonnull final Credential recipientCredential,
+            @Nonnull final Credential originatorCredential, @Nonnull final KeyAgreementParameters parameters)
+                throws KeyAgreementException;
+    
+    /**
+     * Derive a {@link SecretKey} from a given secret.
+     * 
+     * @param secret the input secret
+     * @param keyAlgorithm the JCA key algorithm for the derived key
+     * @param keyLength the key length for the derived key
+     * @param parameters the key agreement parameters
+     * 
+     * @return the derived secret key
+     * 
+     * @throws KeyAgreementException
+     */
+    @Nonnull protected abstract SecretKey deriveSecretKey(@Nonnull final byte[] secret,
+            @Nonnull final String keyAlgorithm, @Nonnull final Integer keyLength,
+            @Nonnull final KeyAgreementParameters parameters) throws KeyAgreementException;
+    
+    /**
+     * Build the final {@link KeyAgreementCredential} from the given inputs.
+     * 
+     * @param derivedKey the derived secret key
+     * @param recipientCredential the recipient credential
+     * @param originatorCredential the originator credential
+     * @param parameters the key agreement parameters
+     * 
+     * @return the new key agreement credential
+     * 
+     * @throws KeyAgreementException
+     */
+    @Nonnull protected KeyAgreementCredential buildKeyAgreementCredential(@Nonnull final SecretKey derivedKey,
+            @Nonnull final Credential recipientCredential, @Nonnull final Credential originatorCredential,
+            @Nonnull final KeyAgreementParameters parameters) throws KeyAgreementException {
+        
+        final KeyAgreementCredential cred = new BasicKeyAgreementCredential(derivedKey, getAlgorithm(),
+                originatorCredential, recipientCredential);
+        cred.getParameters().addAll(parameters);
+        
+        return cred;
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/BasicKeyAgreementCredential.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/BasicKeyAgreementCredential.java
new file mode 100644
index 000000000..13d0b864b
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/BasicKeyAgreementCredential.java
@@ -0,0 +1,86 @@
+/*
+ * 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.agreement.impl;
+
+import javax.annotation.Nonnull;
+import javax.crypto.SecretKey;
+
+import org.opensaml.security.credential.BasicCredential;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.xmlsec.agreement.KeyAgreementCredential;
+import org.opensaml.xmlsec.agreement.KeyAgreementParameters;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Basic implementation of {@link KeyAgreementCredential}.
+ */
+public class BasicKeyAgreementCredential extends BasicCredential implements KeyAgreementCredential {
+    
+    /** Algorithm URI. */
+    @Nonnull private String algorithm;
+    
+    /** Originator credential. */
+    @Nonnull private Credential originatorCredential;
+
+    /** Recipient credential. */
+    @Nonnull private Credential recipientCredential;
+    
+    /** Parameters. */
+    @Nonnull private KeyAgreementParameters parameters;
+
+    /**
+     * Constructor.
+     *
+     * @param derivedKey the derived secret key
+     * @param agreementAlgorithm the key agreement algorithm
+     * @param originator the originator credential
+     * @param recipient the recipient credential
+     */
+    public BasicKeyAgreementCredential(@Nonnull final SecretKey derivedKey, @Nonnull final String agreementAlgorithm,
+            @Nonnull final Credential originator, @Nonnull final Credential recipient) {
+        
+        super(Constraint.isNotNull(derivedKey, "SecretKey was null"));
+        algorithm = Constraint.isNotNull(StringSupport.trimOrNull(agreementAlgorithm), "Algorithm was null");
+        originatorCredential = Constraint.isNotNull(originator, "Originator credential was null");
+        recipientCredential = Constraint.isNotNull(recipient, "Recipient credential was null");
+        parameters = new KeyAgreementParameters();
+    }
+
+    /** {@inheritDoc} */
+    @Nonnull public String getAlgorithm() {
+        return algorithm;
+    }
+
+    /** {@inheritDoc} */
+    @Nonnull public Credential getOriginatorCredential() {
+        return originatorCredential;
+    }
+
+    /** {@inheritDoc} */
+    @Nonnull public Credential getRecipientCredential() {
+        return recipientCredential;
+    }
+
+    /** {@inheritDoc} */
+    @Nonnull public KeyAgreementParameters getParameters() {
+        return parameters;
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/ECDHKeyAgreementProcessor.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/ECDHKeyAgreementProcessor.java
new file mode 100644
index 000000000..6cfb0d51a
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/ECDHKeyAgreementProcessor.java
@@ -0,0 +1,89 @@
+/*
+ * 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.agreement.impl;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.KeyPair;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.interfaces.ECPrivateKey;
+import java.security.interfaces.ECPublicKey;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.security.credential.BasicCredential;
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.crypto.ec.ECSupport;
+import org.opensaml.xmlsec.agreement.KeyAgreementException;
+import org.opensaml.xmlsec.agreement.KeyAgreementParameters;
+import org.opensaml.xmlsec.agreement.KeyAgreementProcessor;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+
+/**
+ * Implementation of {@link KeyAgreementProcessor} which performs Elliptic Curve Diffie-Hellman (ECDH)
+ * Ephemeral-Static Mode key agreement as defined in XML Encryption 1.1.
+ */
+public class ECDHKeyAgreementProcessor extends AbstractDerivationKeyAgreementProcessor {
+
+    /** {@inheritDoc} */
+    public String getAlgorithm() {
+        return EncryptionConstants.ALGO_ID_KEYAGREEMENT_ECDH_ES;
+    }
+
+    /** {@inheritDoc} */
+    protected Credential obtainOriginatorCredential(@Nonnull final Credential recipientCredential,
+            @Nonnull final KeyAgreementParameters parameters) throws KeyAgreementException {
+        
+        if (!ECPublicKey.class.isInstance(recipientCredential.getPublicKey())) {
+            throw new KeyAgreementException("Recipient credential's public key is not an instance of ECPublicKey");
+        }
+        
+        final ECPublicKey recipientPublicKey = ECPublicKey.class.cast(recipientCredential.getPublicKey());
+        
+        try {
+            final KeyPair originatorKeyPair = ECSupport.generateCompatibleKeyPair(recipientPublicKey, null);
+            return new BasicCredential(originatorKeyPair.getPublic(), originatorKeyPair.getPrivate());
+        } catch (final NoSuchAlgorithmException | NoSuchProviderException | InvalidAlgorithmParameterException e) {
+            throw new KeyAgreementException("Error generating originator KeyPair from recipient EC public key", e);
+        }
+    }
+
+    /** {@inheritDoc} */
+    protected byte[] generateAgreementSecret(@Nonnull final Credential recipientCredential,
+            @Nonnull final Credential originatorCredential, @Nonnull final KeyAgreementParameters parameters)
+                    throws KeyAgreementException {
+        
+        if (!ECPublicKey.class.isInstance(recipientCredential.getPublicKey())) {
+            throw new KeyAgreementException("Recipient credential's public key is not an instance of ECPublicKey");
+        }
+        if (!ECPrivateKey.class.isInstance(originatorCredential.getPrivateKey())) {
+            throw new KeyAgreementException("Originator credential's private key is not an instance of ECPublicKey");
+        }
+        
+        final ECPublicKey recipient = ECPublicKey.class.cast(recipientCredential.getPublicKey());
+        final ECPrivateKey originator = ECPrivateKey.class.cast(originatorCredential.getPrivateKey());
+        
+        try {
+            return ECSupport.performKeyAgreement(recipient, originator, null);
+        } catch (final InvalidKeyException | NoSuchAlgorithmException | NoSuchProviderException e) {
+            throw new KeyAgreementException("Error generating secret from recipient and originator EC keys", e);
+        }
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/KANonce.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/KANonce.java
new file mode 100644
index 000000000..069847762
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/KANonce.java
@@ -0,0 +1,65 @@
+/*
+ * 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.agreement.impl;
+
+import javax.annotation.Nonnull;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.xmlsec.agreement.XMLExpressableKeyAgreementParameter;
+
+import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.primitive.StringSupport;
+
+/**
+ * Key agreement parameter to support use of {@link org.opensaml.xmlsec.encryption.KANonce} values.
+ */
+public class KANonce implements XMLExpressableKeyAgreementParameter {
+    
+    /** Base64-encoded nonce value. */
+    @Nonnull private String value;
+
+    /**
+     * Constructor.
+     *
+     * @param newValue the new nonce value
+     */
+    public KANonce(@Nonnull final String newValue) {
+        value = Constraint.isNotNull(StringSupport.trimOrNull(newValue), "Nonce value was null or empty");
+    }
+    
+    /**
+     * Get the Base64-encoded nonce value.
+     * 
+     * @return the nonce value
+     */
+    @Nonnull public String getValue() {
+        return value;
+    }
+
+    /** {@inheritDoc} */
+    public XMLObject buildXMLObject() {
+        final org.opensaml.xmlsec.encryption.KANonce nonce =
+                (org.opensaml.xmlsec.encryption.KANonce) XMLObjectSupport
+                    .buildXMLObject(org.opensaml.xmlsec.encryption.KANonce.DEFAULT_ELEMENT_NAME);
+        
+        nonce.setValue(getValue());
+        return nonce;
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/package-info.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/package-info.java
new file mode 100644
index 000000000..1bc51d36f
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/agreement/impl/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Implementation components related to key agreement operations. */
+package org.opensaml.xmlsec.agreement.impl;
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/ConcatKDF.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/ConcatKDF.java
new file mode 100644
index 000000000..4be44939c
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/ConcatKDF.java
@@ -0,0 +1,66 @@
+/*
+ * 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.derivation.impl;
+
+import javax.annotation.Nonnull;
+import javax.crypto.SecretKey;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.xmlsec.derivation.KeyDerivation;
+import org.opensaml.xmlsec.derivation.KeyDerivationException;
+import org.opensaml.xmlsec.encryption.ConcatKDFParams;
+import org.opensaml.xmlsec.encryption.KeyDerivationMethod;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+
+/**
+ * Implementation of ConcatKDF key derivation as defined in XML Encryption 1.1.
+ */
+public class ConcatKDF implements KeyDerivation {
+
+    /** {@inheritDoc} */
+    public String getAlgorithm() {
+        return EncryptionConstants.ALGO_ID_KEYDERIVATION_CONCATKDF;
+    }
+
+    /** {@inheritDoc} */
+    public SecretKey derive(@Nonnull final byte[] secret, @Nonnull final String keyAlgorithm,
+            @Nonnull final Integer keyLength) throws KeyDerivationException {
+        
+        // TODO Auto-generated method stub
+        
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public XMLObject buildXMLObject() {
+        final KeyDerivationMethod method =
+                (KeyDerivationMethod) XMLObjectSupport.buildXMLObject(KeyDerivationMethod.DEFAULT_ELEMENT_NAME);
+        method.setAlgorithm(getAlgorithm());
+        
+        final ConcatKDFParams params =
+                (ConcatKDFParams) XMLObjectSupport.buildXMLObject(ConcatKDFParams.DEFAULT_ELEMENT_NAME);
+        
+        //TODO populate params based on properties 
+        
+        method.getUnknownXMLObjects().add(params);
+        
+        return method;
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/PBKDF2.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/PBKDF2.java
new file mode 100644
index 000000000..35c7e5fd3
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/PBKDF2.java
@@ -0,0 +1,66 @@
+/*
+ * 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.derivation.impl;
+
+import javax.annotation.Nonnull;
+import javax.crypto.SecretKey;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.xmlsec.derivation.KeyDerivation;
+import org.opensaml.xmlsec.derivation.KeyDerivationException;
+import org.opensaml.xmlsec.encryption.ConcatKDFParams;
+import org.opensaml.xmlsec.encryption.KeyDerivationMethod;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+
+/**
+ * Implementation of PBKDF2 key derivation as defined in XML Encryption 1.1.
+ */
+public class PBKDF2 implements KeyDerivation {
+
+    /** {@inheritDoc} */
+    public String getAlgorithm() {
+        return EncryptionConstants.ALGO_ID_KEYDERIVATION_PBKDF2;
+    }
+
+    /** {@inheritDoc} */
+    public SecretKey derive(@Nonnull final byte[] secret, @Nonnull final String keyAlgorithm,
+            @Nonnull final Integer keyLength) throws KeyDerivationException {
+        
+        // TODO Auto-generated method stub
+        
+        return null;
+    }
+
+    /** {@inheritDoc} */
+    public XMLObject buildXMLObject() {
+        final KeyDerivationMethod method =
+                (KeyDerivationMethod) XMLObjectSupport.buildXMLObject(KeyDerivationMethod.DEFAULT_ELEMENT_NAME);
+        method.setAlgorithm(getAlgorithm());
+        
+        final ConcatKDFParams params =
+                (ConcatKDFParams) XMLObjectSupport.buildXMLObject(ConcatKDFParams.DEFAULT_ELEMENT_NAME);
+        
+        //TODO populate params based on properties 
+        
+        method.getUnknownXMLObjects().add(params);
+        
+        return method;
+    }
+
+}
diff --git a/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/package-info.java b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/package-info.java
new file mode 100644
index 000000000..9948bebe6
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/main/java/org/opensaml/xmlsec/derivation/impl/package-info.java
@@ -0,0 +1,19 @@
+/*
+ * 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.
+ */
+
+/** Implementation components related to key derivation operations. */
+package org.opensaml.xmlsec.derivation.impl;
\ No newline at end of file
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/agreement/impl/ECDHKeyAgreementProcessorTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/agreement/impl/ECDHKeyAgreementProcessorTest.java
new file mode 100644
index 000000000..1d8f51daf
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/agreement/impl/ECDHKeyAgreementProcessorTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.agreement.impl;
+
+import java.security.KeyPair;
+import java.security.spec.ECGenParameterSpec;
+
+import org.opensaml.security.credential.Credential;
+import org.opensaml.security.credential.CredentialSupport;
+import org.opensaml.security.crypto.JCAConstants;
+import org.opensaml.security.crypto.KeySupport;
+import org.opensaml.xmlsec.agreement.KeyAgreementCredential;
+import org.opensaml.xmlsec.agreement.KeyAgreementException;
+import org.opensaml.xmlsec.agreement.KeyAgreementParameters;
+import org.opensaml.xmlsec.derivation.impl.MockKeyDerivation;
+import org.opensaml.xmlsec.encryption.support.EncryptionConstants;
+import org.testng.Assert;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ *
+ */
+public class ECDHKeyAgreementProcessorTest {
+    
+    private ECDHKeyAgreementProcessor processor;
+    
+    @BeforeMethod
+    public void setUp() {
+        processor = new ECDHKeyAgreementProcessor();
+    }
+    
+    @Test
+    public void basic() throws Exception {
+        KeyPair kp = KeySupport.generateKeyPair("EC", new ECGenParameterSpec("secp256r1"), null);
+        Credential recipientCredential = CredentialSupport.getSimpleCredential(kp.getPublic(), null);
+        
+        KeyAgreementParameters params = new KeyAgreementParameters();
+        params.add(new MockKeyDerivation()); 
+        params.add(new KANonce("someBase64")); 
+        
+        KeyAgreementCredential keyAgreementCredential = processor.execute(recipientCredential,
+                JCAConstants.KEY_ALGO_AES,
+                128,
+                params);
+        
+        Assert.assertNotNull(keyAgreementCredential);
+        
+        Assert.assertNotNull(keyAgreementCredential.getSecretKey());
+        Assert.assertEquals(keyAgreementCredential.getSecretKey().getAlgorithm(), JCAConstants.KEY_ALGO_AES);
+        Assert.assertEquals(KeySupport.getKeyLength(keyAgreementCredential.getSecretKey()), Integer.valueOf(128));
+        
+        Assert.assertNull(keyAgreementCredential.getPublicKey());
+        Assert.assertNull(keyAgreementCredential.getPrivateKey());
+        
+        Assert.assertNotNull(keyAgreementCredential.getRecipientCredential());
+        Assert.assertNotNull(keyAgreementCredential.getRecipientCredential().getPublicKey());
+        Assert.assertNull(keyAgreementCredential.getRecipientCredential().getSecretKey());
+        
+        Assert.assertNotNull(keyAgreementCredential.getOriginatorCredential());
+        Assert.assertNotNull(keyAgreementCredential.getOriginatorCredential().getPublicKey());
+        Assert.assertNotNull(keyAgreementCredential.getOriginatorCredential().getPrivateKey());
+        Assert.assertNull(keyAgreementCredential.getOriginatorCredential().getSecretKey());
+        
+        Assert.assertEquals(keyAgreementCredential.getAlgorithm(), EncryptionConstants.ALGO_ID_KEYAGREEMENT_ECDH_ES);
+        
+        Assert.assertEquals(keyAgreementCredential.getParameters().size(), 2);
+        Assert.assertTrue(keyAgreementCredential.getParameters().contains(MockKeyDerivation.class));
+        Assert.assertTrue(keyAgreementCredential.getParameters().contains(KANonce.class));
+        Assert.assertEquals(keyAgreementCredential.getParameters().get(KANonce.class).getValue(), "someBase64");
+        
+    }
+
+    @Test(expectedExceptions = KeyAgreementException.class)
+    public void nonECCred() throws Exception {
+        KeyPair kp = KeySupport.generateKeyPair("RSA", 2048, null);
+        Credential recipientCredential = CredentialSupport.getSimpleCredential(kp.getPublic(), null);
+        
+        KeyAgreementParameters params = new KeyAgreementParameters();
+        params.add(new MockKeyDerivation()); 
+        params.add(new KANonce("someBase64")); 
+        
+        processor.execute(recipientCredential,
+                JCAConstants.KEY_ALGO_AES,
+                128,
+                params);
+    }
+    
+    @Test(expectedExceptions = KeyAgreementException.class)
+    public void keyDerivationError() throws Exception {
+        KeyPair kp = KeySupport.generateKeyPair("EC", new ECGenParameterSpec("secp256r1"), null);
+        Credential recipientCredential = CredentialSupport.getSimpleCredential(kp.getPublic(), null);
+        
+        KeyAgreementParameters params = new KeyAgreementParameters();
+        params.add(new MockKeyDerivation()); 
+        params.add(new KANonce("someBase64")); 
+        
+        processor.execute(recipientCredential,
+                "INVALID",
+                128,
+                params);
+    }
+    
+    @Test(expectedExceptions = KeyAgreementException.class)
+    public void missingKeyDerivationParam() throws Exception {
+        KeyPair kp = KeySupport.generateKeyPair("EC", new ECGenParameterSpec("secp256r1"), null);
+        Credential recipientCredential = CredentialSupport.getSimpleCredential(kp.getPublic(), null);
+        
+        KeyAgreementParameters params = new KeyAgreementParameters();
+        params.add(new KANonce("someBase64")); 
+        
+        processor.execute(recipientCredential,
+                JCAConstants.KEY_ALGO_AES,
+                128,
+                params);
+    }
+        
+}
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/agreement/impl/KANonceTest.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/agreement/impl/KANonceTest.java
new file mode 100644
index 000000000..b2dffd23a
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/agreement/impl/KANonceTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.agreement.impl;
+
+import org.opensaml.core.testing.OpenSAMLInitBaseTestCase;
+import org.opensaml.core.xml.XMLObject;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
+
+/**
+ *
+ */
+public class KANonceTest extends OpenSAMLInitBaseTestCase  {
+    
+    @Test
+    public void basic() {
+        KANonce nonce = new KANonce("   someBase64==   ");
+        Assert.assertEquals(nonce.getValue(), "someBase64==");
+        
+        XMLObject xmlObject = nonce.buildXMLObject();
+        Assert.assertNotNull(xmlObject);
+        Assert.assertTrue(org.opensaml.xmlsec.encryption.KANonce.class.isInstance(xmlObject));
+        org.opensaml.xmlsec.encryption.KANonce xmlNonce = org.opensaml.xmlsec.encryption.KANonce.class.cast(xmlObject);
+        Assert.assertEquals(xmlNonce.getValue(), "someBase64==");
+        
+        try {
+            new KANonce("    ");
+            Assert.fail("KANonce accepted illegal empty value");
+        } catch (ConstraintViolationException e) {
+            // expected, do nothing
+        }
+    }
+    
+}
diff --git a/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/derivation/impl/MockKeyDerivation.java b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/derivation/impl/MockKeyDerivation.java
new file mode 100644
index 000000000..61e4f6ae8
--- /dev/null
+++ b/opensaml-xmlsec-impl/src/test/java/org/opensaml/xmlsec/derivation/impl/MockKeyDerivation.java
@@ -0,0 +1,58 @@
+/*
+ * 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.derivation.impl;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+
+import javax.crypto.SecretKey;
+
+import org.opensaml.core.xml.XMLObject;
+import org.opensaml.core.xml.util.XMLObjectSupport;
+import org.opensaml.security.crypto.KeySupport;
+import org.opensaml.xmlsec.derivation.KeyDerivation;
+import org.opensaml.xmlsec.derivation.KeyDerivationException;
+import org.opensaml.xmlsec.encryption.KeyDerivationMethod;
+
+/**
+ * Mock key derivation for testing.
+ */
+public class MockKeyDerivation implements KeyDerivation {
+
+    /** {@inheritDoc} */
+    public XMLObject buildXMLObject() {
+        final KeyDerivationMethod method = (KeyDerivationMethod) XMLObjectSupport.buildXMLObject(KeyDerivationMethod.DEFAULT_ELEMENT_NAME);
+        method.setAlgorithm(getAlgorithm());
+        return method;
+    }
+
+    /** {@inheritDoc} */
+    public String getAlgorithm() {
+        return "urn:test:MockKeyDerivation";
+    }
+
+    /** {@inheritDoc} */
+    public SecretKey derive(byte[] secret, String keyAlgorithm, Integer keyLength) throws KeyDerivationException {
+        try {
+            return KeySupport.generateKey(keyAlgorithm, keyLength, null);
+        } catch (NoSuchAlgorithmException | NoSuchProviderException e) {
+            throw new KeyDerivationException("Error generating mock derived key", e);
+        }
+    }
+
+}

-- 
To stop receiving notification emails like this one, please contact
the administrator of this repository.


More information about the commits mailing list