[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