You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2023/01/20 09:52:06 UTC
[santuario-xml-security-java] branch main updated: Support for EdDSA: Ed25519 and Ed448 (#90)
This is an automated email from the ASF dual-hosted git repository.
coheigea pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/santuario-xml-security-java.git
The following commit(s) were added to refs/heads/main by this push:
new 2695e32d Support for EdDSA: Ed25519 and Ed448 (#90)
2695e32d is described below
commit 2695e32d6acde43a0ff9123bd25781b8e28eb63f
Author: jrihtarsic <jr...@gmail.com>
AuthorDate: Fri Jan 20 10:52:00 2023 +0100
Support for EdDSA: Ed25519 and Ed448 (#90)
* Fix issue when parsing invalid xpointer URI. Code now throws
XMLSignatureException instead of StringIndexOutOfBoundsException.
* Updating enforcer plugin to 3.0.0
* [SANTUARIO-586]sync JDK-8186958: better calculations for HashMap constructor parameter calculation
* Updating Log4J to 2.17.2
* Updating NOTICE year
* [maven-release-plugin] prepare release xmlsec-2.3.1
* [maven-release-plugin] prepare for next development iteration
* Bumping provider to 2.32 after release
* Updating to Log4J 2.18.0
* Fixing BouncyCastle dependency
* SANTUARIO-593 - Remove here() function support from Apache Santuario (#71)
* SANTUARIO-593 - Remove here() function support from Apache Santuario
* Adding Baltimore23XalanTest
* [maven-release-plugin] prepare release xmlsec-2.3.2
* [maven-release-plugin] prepare for next development iteration
* Updating Version after release
* Fix for https://bugs.openjdk.org/browse/JDK-8287246.
* Updating to Jubit 5.9.1
* Bump woodstox-core from 6.2.8 to 6.4.0 (#80)
Bumps [woodstox-core](https://github.com/FasterXML/woodstox) from 6.2.8 to 6.4.0.
- [Release notes](https://github.com/FasterXML/woodstox/releases)
- [Commits](https://github.com/FasterXML/woodstox/compare/woodstox-core-6.2.8...woodstox-core-6.4.0)
---
updated-dependencies:
- dependency-name: com.fasterxml.woodstox:woodstox-core
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <su...@github.com>
Signed-off-by: dependabot[bot] <su...@github.com>
Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
* Allow SLF4J 2+ for OSGi
* Bump bcprov-jdk18on from 1.71 to 1.72 (#79)
Bumps [bcprov-jdk18on](https://github.com/bcgit/bc-java) from 1.71 to 1.72.
- [Release notes](https://github.com/bcgit/bc-java/releases)
- [Changelog](https://github.com/bcgit/bc-java/blob/master/docs/releasenotes.html)
- [Commits](https://github.com/bcgit/bc-java/commits)
---
updated-dependencies:
- dependency-name: org.bouncycastle:bcprov-jdk18on
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <su...@github.com>
Signed-off-by: dependabot[bot] <su...@github.com>
Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
* Bump maven-bundle-plugin from 5.1.4 to 5.1.8 (#72)
Bumps maven-bundle-plugin from 5.1.4 to 5.1.8.
---
updated-dependencies:
- dependency-name: org.apache.felix:maven-bundle-plugin
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot] <su...@github.com>
Signed-off-by: dependabot[bot] <su...@github.com>
Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
* Bump maven-compiler-plugin from 3.8.1 to 3.10.1 (#74)
Bumps [maven-compiler-plugin](https://github.com/apache/maven-compiler-plugin) from 3.8.1 to 3.10.1.
- [Release notes](https://github.com/apache/maven-compiler-plugin/releases)
- [Commits](https://github.com/apache/maven-compiler-plugin/compare/maven-compiler-plugin-3.8.1...maven-compiler-plugin-3.10.1)
---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-compiler-plugin
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <su...@github.com>
Signed-off-by: dependabot[bot] <su...@github.com>
Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
* Support for EdDSA: Ed25519 and Ed448
* Fix comments.
* Add tests for EdDSA(Ed22519 and Ed448) XML signature validation.
Add activation of BouncyCastleProvider for EdDSA tests only when JDK is before the JDK 15.
* Add basic JSR 105 EdDSA signature validation tests
* Add basic JSR 105 EdDSA signature creation tests
* Fix the License headers for new classes
Signed-off-by: dependabot[bot] <su...@github.com>
Co-authored-by: Sean Mullan <se...@oracle.com>
Co-authored-by: Colm O hEigeartaigh <co...@apache.org>
Co-authored-by: XenoAmess <xe...@gmail.com>
Co-authored-by: Colm O hEigeartaigh <co...@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49...@users.noreply.github.com>
Co-authored-by: Joze RIHTARSIC <jo...@ext.ec.europa.eu>
---
pom.xml | 6 +
.../internal/dom/AbstractDOMSignatureMethod.java | 2 +-
.../xml/dsig/internal/dom/DOMSignatureMethod.java | 95 +++++++++
.../dsig/internal/dom/DOMXMLSignatureFactory.java | 4 +
.../apache/xml/security/algorithms/JCEMapper.java | 8 +
.../security/algorithms/SignatureAlgorithm.java | 11 +-
.../algorithms/implementations/SignatureEDDSA.java | 224 ++++++++++++++++++++
.../org/apache/xml/security/resource/config.xml | 5 +
.../xml/security/signature/XMLSignature.java | 8 +
.../xml/crypto/test/dsig/EdDSATestAbstract.java | 70 ++++++
.../xml/crypto/test/dsig/SignatureValidator.java | 16 +-
.../test/dsig/SignatureValidatorEdDSATest.java | 68 ++++++
.../crypto/test/dsig/XMLSignatureEdDSATest.java | 148 +++++++++++++
.../test/dom/signature/EDDSASignatureTest.java | 235 +++++++++++++++++++++
.../eddsa/envelopingInvalidSignatureEd25519.xml | 31 +++
.../dsig/eddsa/envelopingInvalidSignatureEd448.xml | 32 +++
.../dsig/eddsa/envelopingSignatureEd25519.xml | 31 +++
.../crypto/dsig/eddsa/envelopingSignatureEd448.xml | 32 +++
.../apache/xml/security/samples/input/eddsa.p12 | Bin 0 -> 1977 bytes
.../samples/input/eddsaEd25519Signature.xml | 34 +++
.../security/samples/input/eddsaEd448Signature.xml | 35 +++
21 files changed, 1086 insertions(+), 9 deletions(-)
diff --git a/pom.xml b/pom.xml
index c9339fb8..c063d23a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -589,6 +589,12 @@
<version>${junit.version}</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>org.junit.jupiter</groupId>
+ <artifactId>junit-jupiter-params</artifactId>
+ <version>${junit.version}</version>
+ <scope>test</scope>
+ </dependency>
<dependency>
<groupId>org.xmlunit</groupId>
<artifactId>xmlunit-core</artifactId>
diff --git a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java
index 7bb19c0e..b81cb99a 100644
--- a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java
+++ b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java
@@ -45,7 +45,7 @@ abstract class AbstractDOMSignatureMethod extends DOMStructure
implements SignatureMethod {
// denotes the type of signature algorithm
- enum Type { DSA, RSA, ECDSA, HMAC }
+ enum Type { DSA, RSA, ECDSA, EDDSA, HMAC }
/**
* Verifies the passed-in signature with the specified key, using the
diff --git a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
index ef8c9f07..b92b10b3 100644
--- a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
+++ b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java
@@ -74,6 +74,12 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
static final String DSA_SHA256 =
"http://www.w3.org/2009/xmldsig11#dsa-sha256";
+ // see RFC 9231 for these algorithm definitions
+ static final String ED25519 =
+ "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519";
+ static final String ED448 =
+ "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448";
+
// see RFC 6931 for these algorithm definitions
static final String ECDSA_RIPEMD160 =
"http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160";
@@ -212,6 +218,10 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
return new DOMHMACSignatureMethod.SHA512(smElem);
} else if (alg.equals(DOMHMACSignatureMethod.HMAC_RIPEMD160)) {
return new DOMHMACSignatureMethod.RIPEMD160(smElem);
+ } else if (alg.equals(ED25519)) {
+ return new EDDSA_ED25519(smElem);
+ } else if (alg.equals(ED448)) {
+ return new EDDSA_ED448(smElem);
} else {
throw new MarshalException
("unsupported SignatureMethod algorithm: " + alg);
@@ -469,6 +479,39 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
}
}
+ abstract static class AbstractEDDSASignatureMethod
+ extends DOMSignatureMethod {
+
+
+ AbstractEDDSASignatureMethod(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ super(params);
+ }
+
+ AbstractEDDSASignatureMethod(Element dmElem) throws MarshalException {
+ super(dmElem);
+ }
+
+ /**
+ * Returns {@code sig}. No extra formatting is necessary for EDDSA
+ * See the RFC8032
+ */
+ @Override
+ byte[] postSignFormat(Key key, byte[] sig) {
+ return sig;
+ }
+
+ /**
+ * Returns {@code sig}. No extra formatting is necessary for EDDSA
+ * See the RFC8032
+ */
+ @Override
+ byte[] preVerifyFormat(Key key, byte[] sig) {
+ return sig;
+ }
+
+ }
+
static final class SHA1withRSA extends AbstractRSASignatureMethod {
SHA1withRSA(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException {
@@ -903,4 +946,56 @@ public abstract class DOMSignatureMethod extends AbstractDOMSignatureMethod {
}
}
+ static final class EDDSA_ED25519 extends AbstractEDDSASignatureMethod {
+
+ EDDSA_ED25519(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ super(params);
+ }
+
+ EDDSA_ED25519(Element dmElem) throws MarshalException {
+ super(dmElem);
+ }
+
+ @Override
+ public String getAlgorithm() {
+ return ED25519;
+ }
+
+ @Override
+ String getJCAAlgorithm() {
+ return "Ed25519";
+ }
+
+ @Override
+ Type getAlgorithmType() {
+ return Type.EDDSA;
+ }
+ }
+
+ static final class EDDSA_ED448 extends AbstractEDDSASignatureMethod {
+ EDDSA_ED448(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException {
+ super(params);
+ }
+
+ EDDSA_ED448(Element dmElem) throws MarshalException {
+ super(dmElem);
+ }
+
+ @Override
+ public String getAlgorithm() {
+ return ED448;
+ }
+
+ @Override
+ String getJCAAlgorithm() {
+ return "Ed448";
+ }
+
+ @Override
+ Type getAlgorithmType() {
+ return Type.EDDSA;
+ }
+ }
}
diff --git a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java
index 2c974ced..1f8b7e56 100644
--- a/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java
+++ b/src/main/java/org/apache/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java
@@ -298,6 +298,10 @@ public final class DOMXMLSignatureFactory extends XMLSignatureFactory {
return new DOMSignatureMethod.SHA512withECDSA(params);
} else if (algorithm.equals(DOMSignatureMethod.ECDSA_RIPEMD160)) {
return new DOMSignatureMethod.RIPEMD160withECDSA(params);
+ } else if (algorithm.equals(DOMSignatureMethod.ED25519)) {
+ return new DOMSignatureMethod.EDDSA_ED25519(params);
+ } else if (algorithm.equals(DOMSignatureMethod.ED448)) {
+ return new DOMSignatureMethod.EDDSA_ED448(params);
}else {
throw new NoSuchAlgorithmException("unsupported algorithm");
}
diff --git a/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java b/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java
index 6e054d0b..a91724a7 100644
--- a/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java
+++ b/src/main/java/org/apache/xml/security/algorithms/JCEMapper.java
@@ -206,6 +206,14 @@ public class JCEMapper {
XMLSignature.ALGO_ID_SIGNATURE_ECDSA_RIPEMD160,
new Algorithm("EC", "RIPEMD160withECDSA", "Signature")
);
+ algorithmsMap.put(
+ XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED25519,
+ new Algorithm("Ed25519", "Ed25519", "Signature")
+ );
+ algorithmsMap.put(
+ XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED448,
+ new Algorithm("Ed448", "Ed448", "Signature")
+ );
algorithmsMap.put(
XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5,
new Algorithm("", "HmacMD5", "Mac", 0, 0)
diff --git a/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java b/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java
index 519175a5..7db398ef 100644
--- a/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java
+++ b/src/main/java/org/apache/xml/security/algorithms/SignatureAlgorithm.java
@@ -27,10 +27,7 @@ import java.security.spec.AlgorithmParameterSpec;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
-import org.apache.xml.security.algorithms.implementations.IntegrityHmac;
-import org.apache.xml.security.algorithms.implementations.SignatureBaseRSA;
-import org.apache.xml.security.algorithms.implementations.SignatureDSA;
-import org.apache.xml.security.algorithms.implementations.SignatureECDSA;
+import org.apache.xml.security.algorithms.implementations.*;
import org.apache.xml.security.exceptions.AlgorithmAlreadyRegisteredException;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.signature.XMLSignature;
@@ -493,6 +490,12 @@ public class SignatureAlgorithm extends Algorithm {
algorithmHash.put(
XMLSignature.ALGO_ID_SIGNATURE_ECDSA_RIPEMD160, SignatureECDSA.SignatureECDSARIPEMD160.class
);
+ algorithmHash.put(
+ XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED25519, SignatureEDDSA.SignatureEd25519.class
+ );
+ algorithmHash.put(
+ XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED448, SignatureEDDSA.SignatureEd448.class
+ );
algorithmHash.put(
XMLSignature.ALGO_ID_MAC_HMAC_NOT_RECOMMENDED_MD5, IntegrityHmac.IntegrityHmacMD5.class
);
diff --git a/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureEDDSA.java b/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureEDDSA.java
new file mode 100644
index 00000000..b8921343
--- /dev/null
+++ b/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureEDDSA.java
@@ -0,0 +1,224 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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.apache.xml.security.algorithms.implementations;
+
+import org.apache.xml.security.algorithms.JCEMapper;
+import org.apache.xml.security.algorithms.SignatureAlgorithmSpi;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.signature.XMLSignatureException;
+import org.apache.xml.security.utils.XMLUtils;
+
+import java.io.IOException;
+import java.security.*;
+import java.security.spec.AlgorithmParameterSpec;
+
+/**
+ *
+ */
+public abstract class SignatureEDDSA extends SignatureAlgorithmSpi {
+
+ private static final org.slf4j.Logger LOG =
+ org.slf4j.LoggerFactory.getLogger(SignatureEDDSA.class);
+
+ private final Signature signatureAlgorithm;
+
+
+ /**
+ * Constructor SignatureEDDSA
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureEDDSA() throws XMLSignatureException {
+ this(null);
+ }
+
+ public SignatureEDDSA(Provider provider) throws XMLSignatureException {
+ String algorithmID = JCEMapper.translateURItoJCEID(this.engineGetURI());
+ LOG.debug("Created SignatureEDDSA using {}", algorithmID);
+
+ try {
+ if (provider == null) {
+ String providerId = JCEMapper.getProviderId();
+ if (providerId == null) {
+ this.signatureAlgorithm = Signature.getInstance(algorithmID);
+
+ } else {
+ this.signatureAlgorithm = Signature.getInstance(algorithmID, providerId);
+ }
+
+ } else {
+ this.signatureAlgorithm = Signature.getInstance(algorithmID, provider);
+ }
+
+ } catch (NoSuchAlgorithmException | NoSuchProviderException ex) {
+ Object[] exArgs = { algorithmID, ex.getLocalizedMessage() };
+ throw new XMLSignatureException("algorithms.NoSuchAlgorithm", exArgs);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void engineSetParameter(AlgorithmParameterSpec params)
+ throws XMLSignatureException {
+ try {
+ this.signatureAlgorithm.setParameter(params);
+ } catch (InvalidAlgorithmParameterException ex) {
+ throw new XMLSignatureException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected boolean engineVerify(byte[] signature) throws XMLSignatureException {
+ try {
+
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Called SignatureEDDSA.verify() on " + XMLUtils.encodeToString(signature));
+ }
+
+ return this.signatureAlgorithm.verify(signature);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void engineInitVerify(Key publicKey) throws XMLSignatureException {
+ engineInitVerify(publicKey, signatureAlgorithm);
+ }
+
+ /** {@inheritDoc} */
+ protected byte[] engineSign() throws XMLSignatureException {
+ try {
+ return this.signatureAlgorithm.sign();
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void engineInitSign(Key privateKey, SecureRandom secureRandom)
+ throws XMLSignatureException {
+
+ engineInitSign(privateKey, secureRandom, this.signatureAlgorithm);
+ }
+
+ /** {@inheritDoc} */
+ protected void engineInitSign(Key privateKey) throws XMLSignatureException {
+ engineInitSign(privateKey, (SecureRandom)null);
+ }
+
+ /** {@inheritDoc} */
+ protected void engineUpdate(byte[] input) throws XMLSignatureException {
+ try {
+ this.signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void engineUpdate(byte input) throws XMLSignatureException {
+ try {
+ this.signatureAlgorithm.update(input);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected void engineUpdate(byte[] buf, int offset, int len) throws XMLSignatureException {
+ try {
+ this.signatureAlgorithm.update(buf, offset, len);
+ } catch (SignatureException ex) {
+ throw new XMLSignatureException(ex);
+ }
+ }
+
+ /** {@inheritDoc} */
+ protected String engineGetJCEAlgorithmString() {
+ return this.signatureAlgorithm.getAlgorithm();
+ }
+
+ /** {@inheritDoc} */
+ protected String engineGetJCEProviderName() {
+ return this.signatureAlgorithm.getProvider().getName();
+ }
+
+ /** {@inheritDoc} */
+ protected void engineSetHMACOutputLength(int HMACOutputLength)
+ throws XMLSignatureException {
+ throw new XMLSignatureException("algorithms.HMACOutputLengthOnlyForHMAC");
+ }
+
+ /** {@inheritDoc} */
+ protected void engineInitSign(
+ Key signingKey, AlgorithmParameterSpec algorithmParameterSpec
+ ) throws XMLSignatureException {
+ throw new XMLSignatureException("algorithms.CannotUseAlgorithmParameterSpecOnEdDSA");
+ }
+
+ /**
+ * Class SignatureEd25519
+ *
+ */
+ public static class SignatureEd25519 extends SignatureEDDSA {
+ /**
+ * Constructor SignatureEd25519
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureEd25519() throws XMLSignatureException {
+ super();
+ }
+
+ public SignatureEd25519(Provider provider) throws XMLSignatureException {
+ super(provider);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED25519;
+ }
+ }
+
+ /**
+ * Class SignatureEd448
+ */
+ public static class SignatureEd448 extends SignatureEDDSA {
+
+ /**
+ * Constructor SignatureEd448
+ *
+ * @throws XMLSignatureException
+ */
+ public SignatureEd448() throws XMLSignatureException {
+ super();
+ }
+
+ public SignatureEd448(Provider provider) throws XMLSignatureException {
+ super(provider);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public String engineGetURI() {
+ return XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED448;
+ }
+ }
+}
diff --git a/src/main/java/org/apache/xml/security/resource/config.xml b/src/main/java/org/apache/xml/security/resource/config.xml
index e460eb64..326140ee 100644
--- a/src/main/java/org/apache/xml/security/resource/config.xml
+++ b/src/main/java/org/apache/xml/security/resource/config.xml
@@ -128,6 +128,11 @@
JAVACLASS="org.apache.xml.security.algorithms.implementations.SignatureECDSA$SignatureECDSASHA512" />
<SignatureAlgorithm URI="http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160"
JAVACLASS="org.apache.xml.security.algorithms.implementations.SignatureECDSA$SignatureECDSARIPEMD160" />
+
+ <SignatureAlgorithm URI="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519"
+ JAVACLASS="org.apache.xml.security.algorithms.implementations.SignatureEDDSA$SignatureEd25519" />
+ <SignatureAlgorithm URI="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"
+ JAVACLASS="org.apache.xml.security.algorithms.implementations.SignatureEDDSA$SignatureEd448" />
<SignatureAlgorithm URI="http://www.w3.org/2001/04/xmldsig-more#hmac-md5"
JAVACLASS="org.apache.xml.security.algorithms.implementations.IntegrityHmac$IntegrityHmacMD5" />
diff --git a/src/main/java/org/apache/xml/security/signature/XMLSignature.java b/src/main/java/org/apache/xml/security/signature/XMLSignature.java
index 4987431a..19801c04 100644
--- a/src/main/java/org/apache/xml/security/signature/XMLSignature.java
+++ b/src/main/java/org/apache/xml/security/signature/XMLSignature.java
@@ -197,6 +197,14 @@ public final class XMLSignature extends SignatureElementProxy {
public static final String ALGO_ID_SIGNATURE_ECDSA_RIPEMD160 =
"http://www.w3.org/2007/05/xmldsig-more#ecdsa-ripemd160";
+ /**Signature - EDDSA ED25519 */
+ public static final String ALGO_ID_SIGNATURE_EDDSA_ED25519 =
+ "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519";
+
+ /**Signature - EDDSA ED448 */
+ public static final String ALGO_ID_SIGNATURE_EDDSA_ED448 =
+ "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448";
+
/** Signature - Optional RSASSA-PSS */
public static final String ALGO_ID_SIGNATURE_RSA_PSS =
Constants.XML_DSIG_NS_MORE_07_05 + "rsa-pss";
diff --git a/src/test/java/javax/xml/crypto/test/dsig/EdDSATestAbstract.java b/src/test/java/javax/xml/crypto/test/dsig/EdDSATestAbstract.java
new file mode 100644
index 00000000..c5b7a5d5
--- /dev/null
+++ b/src/test/java/javax/xml/crypto/test/dsig/EdDSATestAbstract.java
@@ -0,0 +1,70 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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 javax.xml.crypto.test.dsig;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import java.security.Security;
+
+/**
+ * Abstract/super class for EdDSA signature tests
+ */
+public abstract class EdDSATestAbstract {
+
+ public static final String EDDSA_KS =
+ "src/test/resources/org/apache/xml/security/samples/input/eddsa.p12";
+ public static final String EDDSA_KS_PASSWORD = "security";
+ public static final String EDDSA_KS_TYPE = "PKCS12";
+ private static boolean bcAddedForTheTest = false;
+
+ @org.junit.jupiter.api.BeforeAll
+ public static void beforeAll() {
+ Security.insertProviderAt
+ (new org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI(), 1);
+ // Since JDK 15, the EdDSA algorithms are supported in the default java JCA provider.
+ // Add BouncyCastleProvider only for java versions before JDK 15.
+ boolean isNotJDK15up;
+ try {
+ int javaVersion = Integer.parseInt(System.getProperty("java.specification.version"));
+ isNotJDK15up = javaVersion < 15;
+ } catch (NumberFormatException ex) {
+ isNotJDK15up = true;
+ }
+ if (isNotJDK15up && Security.getProvider(org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME) == null) {
+ Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
+ bcAddedForTheTest = true;
+ }
+ }
+
+ @org.junit.jupiter.api.AfterAll
+ public static void afterAll() {
+ if (bcAddedForTheTest) {
+ Security.removeProvider(org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME);
+ }
+ }
+
+ public void updateIdReferences(DOMValidateContext vc, String elementName, String idAttributeName) {
+ Document doc = vc.getNode().getOwnerDocument();
+ NodeList nl = doc.getElementsByTagName(elementName);
+ vc.setIdAttributeNS((Element) nl.item(0), null, idAttributeName);
+ }
+}
diff --git a/src/test/java/javax/xml/crypto/test/dsig/SignatureValidator.java b/src/test/java/javax/xml/crypto/test/dsig/SignatureValidator.java
index 1d001d41..b3bd195d 100644
--- a/src/test/java/javax/xml/crypto/test/dsig/SignatureValidator.java
+++ b/src/test/java/javax/xml/crypto/test/dsig/SignatureValidator.java
@@ -54,15 +54,23 @@ public class SignatureValidator {
return getValidateContext(fn, ks, true);
}
- public DOMValidateContext getValidateContext(String fn, KeySelector ks, boolean secureValidation)
- throws Exception {
- Document doc = XMLUtils.read(new FileInputStream(new File(dir, fn)), false);
+ public DOMValidateContext getValidateContext(String fn, KeySelector ks, boolean secureValidation) throws Exception {
+ DOMValidateContext domValidateContext;
+ try (FileInputStream inputStream = new FileInputStream(new File(dir, fn))){
+ domValidateContext = getValidateContext(inputStream, ks, secureValidation);
+ domValidateContext.setBaseURI(dir.toURI().toString());
+ }
+ return domValidateContext;
+ }
+
+ public DOMValidateContext getValidateContext(InputStream inputStream, KeySelector ks, boolean secureValidation)
+ throws Exception {
+ Document doc = XMLUtils.read(inputStream, false);
Element sigElement = getSignatureElement(doc);
if (sigElement == null) {
throw new Exception("Couldn't find signature Element");
}
DOMValidateContext vc = new DOMValidateContext(ks, sigElement);
- vc.setBaseURI(dir.toURI().toString());
vc.setProperty("org.apache.jcp.xml.dsig.secureValidation", secureValidation);
return vc;
}
diff --git a/src/test/java/javax/xml/crypto/test/dsig/SignatureValidatorEdDSATest.java b/src/test/java/javax/xml/crypto/test/dsig/SignatureValidatorEdDSATest.java
new file mode 100644
index 00000000..dca8fe8c
--- /dev/null
+++ b/src/test/java/javax/xml/crypto/test/dsig/SignatureValidatorEdDSATest.java
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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 javax.xml.crypto.test.dsig;
+
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.test.KeySelectors;
+import java.nio.file.Paths;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+
+/**
+ * This is a testcase validates various EdDSA XML signatures
+ */
+public class SignatureValidatorEdDSATest extends EdDSATestAbstract {
+
+ private SignatureValidator testInstance;
+
+ @org.junit.jupiter.api.BeforeEach
+ public void before() {
+ String base = System.getProperty("basedir", "./");
+ testInstance = new SignatureValidator(Paths.get(base, "src", "test", "resources", "javax", "xml", "crypto", "dsig", "eddsa").toFile());
+ }
+
+ /**
+ * Validates a signature that references an element with an ID attribute.
+ * The element's ID needs to be registered so that it can be found.
+ */
+ @ParameterizedTest
+ @CsvSource({"envelopingSignatureEd25519.xml,true,Signature failed core validation",
+ "envelopingSignatureEd448.xml,true,Signature failed core validation",
+ "envelopingInvalidSignatureEd25519.xml,false,Invalid signature should fail!",
+ "envelopingInvalidSignatureEd448.xml,false,Invalid signature should fail!"})
+ public void test_enveloping_signature_with_ID(String filename, String result, String message) throws Exception {
+ DOMValidateContext vc = testInstance.getValidateContext
+ (filename, new KeySelectors.RawX509KeySelector());
+ updateIdReferences(vc);
+
+ boolean coreValidity = testInstance.validate(vc);
+ // assert expected result
+ assertEquals(Boolean.valueOf(result), coreValidity, message);
+ }
+
+ private void updateIdReferences(DOMValidateContext vc) {
+ updateIdReferences(vc, "Assertion", "AssertionID");
+ }
+
+}
diff --git a/src/test/java/javax/xml/crypto/test/dsig/XMLSignatureEdDSATest.java b/src/test/java/javax/xml/crypto/test/dsig/XMLSignatureEdDSATest.java
new file mode 100644
index 00000000..d4300e97
--- /dev/null
+++ b/src/test/java/javax/xml/crypto/test/dsig/XMLSignatureEdDSATest.java
@@ -0,0 +1,148 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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 javax.xml.crypto.test.dsig;
+
+
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.test.dom.TestUtils;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvSource;
+import org.w3c.dom.Element;
+
+import javax.xml.crypto.dsig.*;
+import javax.xml.crypto.dsig.dom.DOMSignContext;
+import javax.xml.crypto.dsig.dom.DOMValidateContext;
+import javax.xml.crypto.dsig.keyinfo.KeyInfo;
+import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory;
+import javax.xml.crypto.dsig.keyinfo.X509Data;
+import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
+import javax.xml.crypto.dsig.spec.TransformParameterSpec;
+import javax.xml.crypto.test.KeySelectors;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+
+/**
+ * Unit test for EdDSA javax.xml.crypto.dsig.XMLSignature creation
+ */
+public class XMLSignatureEdDSATest extends EdDSATestAbstract {
+ private final SignatureValidator testInstance = new SignatureValidator(null);
+
+ static {
+ Security.insertProviderAt
+ (new org.apache.jcp.xml.dsig.internal.dom.XMLDSigRI(), 1);
+ }
+
+ @ParameterizedTest
+ @CsvSource({"http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519,ed25519",
+ "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448,ed448",
+ })
+ public void createEdDSASignatureTest(String signatureAlgorithm, String alias) throws Exception {
+ byte[] buff = doSign(signatureAlgorithm, alias);
+ Assertions.assertNotNull(buff);
+ assertValidSignature(buff);
+ }
+
+ public byte[] doSign(String signatureMethod, String alias) throws Exception {
+
+ // create test xml document to sign
+ String signedElementId = "element-id-01";
+ String signedElementName = "SignedElement";
+ org.w3c.dom.Document doc = TestUtils.newDocument();
+ Element root = doc.createElement("RootElement");
+ Element signedElement = doc.createElement(signedElementName);
+ signedElement.setAttribute("id", signedElementId);
+ signedElement.appendChild(doc.createTextNode("Some data to sign"));
+ doc.appendChild(root);
+ root.appendChild(signedElement);
+
+ // get private key and the certificate from the truststore
+ KeyStore keyStore = KeyStore.getInstance(EDDSA_KS_TYPE);
+ keyStore.load(Files.newInputStream(Paths.get(EDDSA_KS)), EDDSA_KS_PASSWORD.toCharArray());
+ X509Certificate certificate = (X509Certificate) keyStore.getCertificate(alias);
+ PrivateKey privateKey =
+ (PrivateKey) keyStore.getKey(alias, EDDSA_KS_PASSWORD.toCharArray());
+
+ // prepare xml signature data
+ Element canonElem =
+ XMLUtils.createElementInSignatureSpace(doc, Constants._TAG_CANONICALIZATIONMETHOD);
+ canonElem.setAttributeNS(
+ null, Constants._ATT_ALGORITHM, Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS
+ );
+
+ //Create XML Signature Factory
+ XMLSignatureFactory xmlSigFactory = XMLSignatureFactory.getInstance("DOM");
+ DOMSignContext domSignCtx = new DOMSignContext(privateKey, doc.getDocumentElement());
+ domSignCtx.setIdAttributeNS(signedElement, null, "id");
+ // reference(s), SignedInfo and KeyInfo
+ Reference ref = xmlSigFactory.newReference("#" + signedElementId, xmlSigFactory.newDigestMethod(DigestMethod.SHA256, null),
+ Collections.singletonList(xmlSigFactory.newTransform(Transform.ENVELOPED,
+ (TransformParameterSpec) null)), null, null);
+ SignedInfo signedInfo = xmlSigFactory.newSignedInfo(
+ xmlSigFactory.newCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE,
+ (C14NMethodParameterSpec) null),
+ xmlSigFactory.newSignatureMethod(signatureMethod, null),
+ Collections.singletonList(ref));
+ KeyInfo keyInfo = createKeyInfo(xmlSigFactory, certificate);
+ //Create the XML Signature
+ XMLSignature xmlSignature = xmlSigFactory.newXMLSignature(signedInfo, keyInfo);
+ //Sign the document
+ xmlSignature.sign(domSignCtx);
+ // serialize the xml to byte array
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+ XMLUtils.outputDOMc14nWithComments(doc, bos);
+ return bos.toByteArray();
+ }
+
+ private KeyInfo createKeyInfo(XMLSignatureFactory fac, X509Certificate cert) {
+ // Create the KeyInfo containing the X509Data.
+ KeyInfoFactory kif = fac.getKeyInfoFactory();
+ List<Object> x509Content = new ArrayList();
+ x509Content.add(cert.getSubjectX500Principal().getName());
+ x509Content.add(cert);
+ X509Data xd = kif.newX509Data(x509Content);
+ return kif.newKeyInfo(Collections.singletonList(xd));
+ }
+
+ private void assertValidSignature(byte[] signedXml) throws Exception {
+ try (InputStream is = new ByteArrayInputStream(signedXml)) {
+ DOMValidateContext vc = testInstance.getValidateContext(is, new KeySelectors.RawX509KeySelector(), false);
+ updateIdReferences(vc, "SignedElement", "id");
+
+ boolean coreValidity = testInstance.validate(vc);
+ // assert expected result
+ assertTrue(coreValidity);
+ }
+ }
+}
diff --git a/src/test/java/org/apache/xml/security/test/dom/signature/EDDSASignatureTest.java b/src/test/java/org/apache/xml/security/test/dom/signature/EDDSASignatureTest.java
new file mode 100644
index 00000000..3bfe74cc
--- /dev/null
+++ b/src/test/java/org/apache/xml/security/test/dom/signature/EDDSASignatureTest.java
@@ -0,0 +1,235 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.apache.xml.security.test.dom.signature;
+
+import org.apache.xml.security.algorithms.SignatureAlgorithm;
+import org.apache.xml.security.c14n.Canonicalizer;
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.test.dom.DSNamespaceContext;
+import org.apache.xml.security.test.dom.TestUtils;
+import org.apache.xml.security.transforms.Transforms;
+import org.apache.xml.security.utils.Constants;
+import org.apache.xml.security.utils.XMLUtils;
+import org.junit.jupiter.api.Assertions;
+import org.w3c.dom.Element;
+
+import javax.xml.crypto.test.dsig.EdDSATestAbstract;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.security.KeyStore;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.cert.X509Certificate;
+
+
+/**
+ * Tests of the EDDSA Ed25519 and Ed448 signatures.
+ * @since 2.3.3.
+ */
+public class EDDSASignatureTest extends EdDSATestAbstract {
+ static {
+ if (!org.apache.xml.security.Init.isInitialized()) {
+ org.apache.xml.security.Init.init();
+ }
+ }
+
+ @org.junit.jupiter.api.Test
+ public void testEd22519() throws Exception {
+
+ KeyStore keyStore = KeyStore.getInstance(EDDSA_KS_TYPE);
+ keyStore.load(Files.newInputStream(Paths.get(EDDSA_KS)), EDDSA_KS_PASSWORD.toCharArray());
+
+ PrivateKey privateKey =
+ (PrivateKey) keyStore.getKey("Ed25519", EDDSA_KS_PASSWORD.toCharArray());
+
+ doVerify(doSign(privateKey, (X509Certificate) keyStore.getCertificate("Ed25519"), null, XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED25519));
+ }
+
+ @org.junit.jupiter.api.Test
+ public void testEd22519VerifyXML() throws Exception {
+
+ try (InputStream xmlSignatureExample
+ = EDDSASignatureTest.class.getResourceAsStream("/org/apache/xml/security/samples/input/eddsaEd25519Signature.xml")) {
+ doVerify(xmlSignatureExample);
+ }
+ }
+
+ @org.junit.jupiter.api.Test
+ public void testEd448VerifyXML() throws Exception {
+
+ try (InputStream xmlSignatureExample
+ = EDDSASignatureTest.class.getResourceAsStream("/org/apache/xml/security/samples/input/eddsaEd448Signature.xml")) {
+ doVerify(xmlSignatureExample);
+ }
+ }
+
+ @org.junit.jupiter.api.Test
+ public void testEd448() throws Exception {
+
+ KeyStore keyStore = KeyStore.getInstance(EDDSA_KS_TYPE);
+ keyStore.load(Files.newInputStream(Paths.get(EDDSA_KS)), EDDSA_KS_PASSWORD.toCharArray());
+
+ PrivateKey privateKey =
+ (PrivateKey) keyStore.getKey("Ed448", EDDSA_KS_PASSWORD.toCharArray());
+
+ doVerify(doSign(privateKey, (X509Certificate) keyStore.getCertificate("Ed448"), null, XMLSignature.ALGO_ID_SIGNATURE_EDDSA_ED448));
+ }
+
+
+ private byte[] doSign(PrivateKey privateKey, X509Certificate x509, PublicKey publicKey, String signAlgorithm) throws Exception {
+ org.w3c.dom.Document doc = TestUtils.newDocument();
+ doc.appendChild(doc.createComment(" Comment before "));
+ Element root = doc.createElementNS("", "RootElement");
+
+ doc.appendChild(root);
+ root.appendChild(doc.createTextNode("Some simple text\n"));
+
+ Element canonElem =
+ XMLUtils.createElementInSignatureSpace(doc, Constants._TAG_CANONICALIZATIONMETHOD);
+ canonElem.setAttributeNS(
+ null, Constants._ATT_ALGORITHM, Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS
+ );
+
+ SignatureAlgorithm signatureAlgorithm =
+ new SignatureAlgorithm(doc, signAlgorithm);
+ XMLSignature sig =
+ new XMLSignature(doc, null, signatureAlgorithm.getElement(), canonElem);
+
+ root.appendChild(sig.getElement());
+ doc.appendChild(doc.createComment(" Comment after "));
+ Transforms transforms = new Transforms(doc);
+ transforms.addTransform(Transforms.TRANSFORM_ENVELOPED_SIGNATURE);
+ transforms.addTransform(Transforms.TRANSFORM_C14N_WITH_COMMENTS);
+ sig.addDocument("", transforms, Constants.ALGO_ID_DIGEST_SHA1);
+
+ if (x509 != null) {
+ sig.addKeyInfo(x509);
+ } else {
+ sig.addKeyInfo(publicKey);
+ }
+ sig.sign(privateKey);
+
+ ByteArrayOutputStream bos = new ByteArrayOutputStream();
+
+ XMLUtils.outputDOMc14nWithComments(doc, bos);
+ return bos.toByteArray();
+ }
+
+ private void doVerify(byte[] signedXml) throws Exception {
+ try (InputStream is = new ByteArrayInputStream(signedXml)) {
+ doVerify(is);
+ }
+ }
+
+ private void doVerify(InputStream is) throws Exception {
+ org.w3c.dom.Document doc = XMLUtils.read(is, false);
+
+ XPathFactory xpf = XPathFactory.newInstance();
+ XPath xpath = xpf.newXPath();
+ xpath.setNamespaceContext(new DSNamespaceContext());
+
+ String expression = "//ds:Signature[1]";
+ Element sigElement =
+ (Element) xpath.evaluate(expression, doc, XPathConstants.NODE);
+ XMLSignature signature = new XMLSignature(sigElement, "");
+
+ signature.addResourceResolver(new XPointerResourceResolver(sigElement));
+
+ KeyInfo ki = signature.getKeyInfo();
+ if (ki == null) {
+ throw new RuntimeException("No keyinfo");
+ }
+ X509Certificate cert = signature.getKeyInfo().getX509Certificate();
+ if (cert != null) {
+ Assertions.assertTrue(signature.checkSignatureValue(cert));
+ } else {
+ Assertions.assertTrue(signature.checkSignatureValue(signature.getKeyInfo().getPublicKey()));
+ }
+ }
+
+/**
+ * DO NOT DELETE THIS COMMENTED OUT METHOD!
+ *
+ * The reason this method is commented out is to avoid introducing explicit
+ * BouncyCastle dependencies.
+ *
+ * Create an X.509 Certificate and associated private key using the Edwards-Curve Digital Signature Algorithm
+ * DSA algorithm, and store in a KeyStore. This method was used to generate the
+ * keystore used for this test
+ * ("src/test/resources/org/apache/xml/security/samples/input/eddsa.p12").
+ * To generate certificte add the: org.bouncycastle::bcpkix-jdk18on
+
+ private static void setUpKeyAndCertificate() throws Exception {
+ String[] algorithms = new String []{"Ed25519","Ed448"};
+ KeyStore keyStore = KeyStore.getInstance("PKCS12");
+ keyStore.load(null, EDDSA_KS_PASSWORD.toCharArray());
+ for (String parameterName:algorithms) {
+
+
+ String signatureAlgName = parameterName;
+
+ java.security.KeyPairGenerator kpg =
+ java.security.KeyPairGenerator.getInstance(parameterName, org.bouncycastle.jce.provider.BouncyCastleProvider.PROVIDER_NAME);
+ org.bouncycastle.jcajce.spec.EdDSAParameterSpec keySpec = new org.bouncycastle.jcajce.spec.EdDSAParameterSpec(parameterName);
+ kpg.initialize(keySpec, new java.security.SecureRandom());
+
+ // Cert data
+ java.security.KeyPair keyPair = kpg.generateKeyPair();
+ long now = System.currentTimeMillis();
+ java.util.Date from_date = new java.util.Date(now);
+ java.util.Calendar cal = new java.util.GregorianCalendar();
+ cal.setTime(from_date);
+ cal.add(java.util.Calendar.YEAR, 4);
+ java.util.Date to_date = cal.getTime();
+
+ org.bouncycastle.asn1.x500.X500Name subject = new org.bouncycastle.asn1.x500.X500Name("CN=XML "+parameterName+" Signature Test,DC=apache,DC=org");
+ org.bouncycastle.cert.X509v3CertificateBuilder certBuilder = new org.bouncycastle.cert.X509v3CertificateBuilder(subject,
+ java.math.BigInteger.valueOf(now), from_date, to_date, subject,
+ SubjectPublicKeyInfo.getInstance(keyPair.getPublic().getEncoded()));
+
+ certBuilder.addExtension(org.bouncycastle.asn1.x509.Extension.basicConstraints, true, new org.bouncycastle.asn1.x509.BasicConstraints(true));
+ certBuilder.addExtension(org.bouncycastle.asn1.x509.Extension.keyUsage, true, new org.bouncycastle.asn1.x509.KeyUsage(org.bouncycastle.asn1.x509.KeyUsage.digitalSignature |
+ org.bouncycastle.asn1.x509.KeyUsage.keyEncipherment |
+ org.bouncycastle.asn1.x509.KeyUsage.keyCertSign |
+ org.bouncycastle.asn1.x509.KeyUsage.cRLSign));
+
+ ContentSigner sigGen = new JcaContentSignerBuilder(signatureAlgName)
+ .build(keyPair.getPrivate());
+
+ X509Certificate x509 = new JcaX509CertificateConverter().getCertificate(certBuilder.build(sigGen));
+
+
+ keyStore.setKeyEntry(
+ parameterName, keyPair.getPrivate(),
+ EDDSA_KS_PASSWORD.toCharArray(), new java.security.cert.Certificate[]{x509}
+ );
+ }
+ keyStore.store(
+ new java.io.FileOutputStream(EDDSA_KS), EDDSA_KS_PASSWORD.toCharArray()
+ );
+ }
+ */
+}
diff --git a/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingInvalidSignatureEd25519.xml b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingInvalidSignatureEd25519.xml
new file mode 100644
index 00000000..92582c52
--- /dev/null
+++ b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingInvalidSignatureEd25519.xml
@@ -0,0 +1,31 @@
+<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519"></ds:SignatureMethod>
+<ds:Reference URI="#foo">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
+<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
+<ds:DigestValue>SaRMZuEOPHiUpJrjWfnciQAmhN8=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>
+TMaM9f+TpFf2oIyEpM5piLK2l9eNs7t4YqhwUPavbkfL51Ms7ff2efDpxQ5QBaV9M6RX5qFZg/1y
+etXA+dOlDw==
+</ds:SignatureValue>
+<ds:KeyInfo>
+<ds:X509Data>
+<ds:X509Certificate>
+MIIBezCCAS2gAwIBAgIGAYR2SB6KMAUGAytlcDBSMSMwIQYDVQQDDBpYTUwgRWQyNTUxOSBTaWdu
+YXR1cmUgVGVzdDEWMBQGCgmSJomT8ixkARkWBmFwYWNoZTETMBEGCgmSJomT8ixkARkWA29yZzAe
+Fw0yMjExMTQxMzE1NDhaFw0yNjExMTQxMzE1NDhaMFIxIzAhBgNVBAMMGlhNTCBFZDI1NTE5IFNp
+Z25hdHVyZSBUZXN0MRYwFAYKCZImiZPyLGQBGRYGYXBhY2hlMRMwEQYKCZImiZPyLGQBGRYDb3Jn
+MCowBQYDK2VwAyEAhxvsjkHukjJDs7Z8NvUNUChup4RKpkfTMPRnseY+SwyjIzAhMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMAUGAytlcANBALRvL/aEAn9WWtPpseszszSWR3Gyn5IS
+qgXKtWbiZIMUTvF7QU8MgkXK8s329fPLCb8+6kvE6K24bxVWpabEEgs=
+</ds:X509Certificate>
+</ds:X509Data>
+</ds:KeyInfo>
+<ds:Object Id="object"><Assertion AssertionID="foo">Some simple text changed after the signature</Assertion></ds:Object></ds:Signature>
diff --git a/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingInvalidSignatureEd448.xml b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingInvalidSignatureEd448.xml
new file mode 100644
index 00000000..7c6c46d6
--- /dev/null
+++ b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingInvalidSignatureEd448.xml
@@ -0,0 +1,32 @@
+<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"></ds:SignatureMethod>
+<ds:Reference URI="#foo">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
+<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
+<ds:DigestValue>SaRMZuEOPHiUpJrjWfnciQAmhN8=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>
+6U+Jj4y/W1S5NBQ++BIaqydoc7RHHkZwFhOJ+xwq9t5PFx4BC2OW71HfWuVgXcEWU5mvDgYRPl2A
+qal9fMV2tDOkqadER/ytKn/hQ1/Tq5WEF0TDCQRd3HuerI0XjCZv/AJPfMUuGPBDUSQp4i3CNTIA
+</ds:SignatureValue>
+<ds:KeyInfo>
+<ds:X509Data>
+<ds:X509Certificate>
+MIIBwjCCAUKgAwIBAgIGAYR2SB8kMAUGAytlcTBQMSEwHwYDVQQDDBhYTUwgRWQ0NDggU2lnbmF0
+dXJlIFRlc3QxFjAUBgoJkiaJk/IsZAEZFgZhcGFjaGUxEzARBgoJkiaJk/IsZAEZFgNvcmcwHhcN
+MjIxMTE0MTMxNTQ4WhcNMjYxMTE0MTMxNTQ4WjBQMSEwHwYDVQQDDBhYTUwgRWQ0NDggU2lnbmF0
+dXJlIFRlc3QxFjAUBgoJkiaJk/IsZAEZFgZhcGFjaGUxEzARBgoJkiaJk/IsZAEZFgNvcmcwQzAF
+BgMrZXEDOgBSokK9a5+Bpmi4vZkdhdvKDJK6AfR5aBo95bEqrdNGli+s+0iTsVvLptAvSNZu2xQK
+88rbOTbGVACjIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMAUGAytlcQNzAF2v
+bxSz55R+nN3FDZKuu/Yhq/jEfjH9i7aAwB0HSKqqq3RiPKl48F1ER7kYwDJjZYmj0SXdCzqZgFVN
+dCb6GgrdFIqxg+DHqfoQ+tM+fvhpkkydTtAvKcUX8xspuQ8C2jv39OzEH2ONzMdtWjjS4H4ZAA==
+</ds:X509Certificate>
+</ds:X509Data>
+</ds:KeyInfo>
+<ds:Object Id="object"><Assertion AssertionID="foo">Some simple text changed after the signature</Assertion></ds:Object></ds:Signature>
diff --git a/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingSignatureEd25519.xml b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingSignatureEd25519.xml
new file mode 100644
index 00000000..cd10795a
--- /dev/null
+++ b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingSignatureEd25519.xml
@@ -0,0 +1,31 @@
+<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519"></ds:SignatureMethod>
+<ds:Reference URI="#foo">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
+<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
+<ds:DigestValue>SaRMZuEOPHiUpJrjWfnciQAmhN8=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>
+TMaM9f+TpFf2oIyEpM5piLK2l9eNs7t4YqhwUPavbkfL51Ms7ff2efDpxQ5QBaV9M6RX5qFZg/1y
+etXA+dOlDw==
+</ds:SignatureValue>
+<ds:KeyInfo>
+<ds:X509Data>
+<ds:X509Certificate>
+MIIBezCCAS2gAwIBAgIGAYR2SB6KMAUGAytlcDBSMSMwIQYDVQQDDBpYTUwgRWQyNTUxOSBTaWdu
+YXR1cmUgVGVzdDEWMBQGCgmSJomT8ixkARkWBmFwYWNoZTETMBEGCgmSJomT8ixkARkWA29yZzAe
+Fw0yMjExMTQxMzE1NDhaFw0yNjExMTQxMzE1NDhaMFIxIzAhBgNVBAMMGlhNTCBFZDI1NTE5IFNp
+Z25hdHVyZSBUZXN0MRYwFAYKCZImiZPyLGQBGRYGYXBhY2hlMRMwEQYKCZImiZPyLGQBGRYDb3Jn
+MCowBQYDK2VwAyEAhxvsjkHukjJDs7Z8NvUNUChup4RKpkfTMPRnseY+SwyjIzAhMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMAUGAytlcANBALRvL/aEAn9WWtPpseszszSWR3Gyn5IS
+qgXKtWbiZIMUTvF7QU8MgkXK8s329fPLCb8+6kvE6K24bxVWpabEEgs=
+</ds:X509Certificate>
+</ds:X509Data>
+</ds:KeyInfo>
+<ds:Object Id="object"><Assertion AssertionID="foo">Some simple text</Assertion></ds:Object></ds:Signature>
\ No newline at end of file
diff --git a/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingSignatureEd448.xml b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingSignatureEd448.xml
new file mode 100644
index 00000000..d5f6486e
--- /dev/null
+++ b/src/test/resources/javax/xml/crypto/dsig/eddsa/envelopingSignatureEd448.xml
@@ -0,0 +1,32 @@
+<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"></ds:SignatureMethod>
+<ds:Reference URI="#foo">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
+<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
+<ds:DigestValue>SaRMZuEOPHiUpJrjWfnciQAmhN8=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>
+6U+Jj4y/W1S5NBQ++BIaqydoc7RHHkZwFhOJ+xwq9t5PFx4BC2OW71HfWuVgXcEWU5mvDgYRPl2A
+qal9fMV2tDOkqadER/ytKn/hQ1/Tq5WEF0TDCQRd3HuerI0XjCZv/AJPfMUuGPBDUSQp4i3CNTIA
+</ds:SignatureValue>
+<ds:KeyInfo>
+<ds:X509Data>
+<ds:X509Certificate>
+MIIBwjCCAUKgAwIBAgIGAYR2SB8kMAUGAytlcTBQMSEwHwYDVQQDDBhYTUwgRWQ0NDggU2lnbmF0
+dXJlIFRlc3QxFjAUBgoJkiaJk/IsZAEZFgZhcGFjaGUxEzARBgoJkiaJk/IsZAEZFgNvcmcwHhcN
+MjIxMTE0MTMxNTQ4WhcNMjYxMTE0MTMxNTQ4WjBQMSEwHwYDVQQDDBhYTUwgRWQ0NDggU2lnbmF0
+dXJlIFRlc3QxFjAUBgoJkiaJk/IsZAEZFgZhcGFjaGUxEzARBgoJkiaJk/IsZAEZFgNvcmcwQzAF
+BgMrZXEDOgBSokK9a5+Bpmi4vZkdhdvKDJK6AfR5aBo95bEqrdNGli+s+0iTsVvLptAvSNZu2xQK
+88rbOTbGVACjIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMAUGAytlcQNzAF2v
+bxSz55R+nN3FDZKuu/Yhq/jEfjH9i7aAwB0HSKqqq3RiPKl48F1ER7kYwDJjZYmj0SXdCzqZgFVN
+dCb6GgrdFIqxg+DHqfoQ+tM+fvhpkkydTtAvKcUX8xspuQ8C2jv39OzEH2ONzMdtWjjS4H4ZAA==
+</ds:X509Certificate>
+</ds:X509Data>
+</ds:KeyInfo>
+<ds:Object Id="object"><Assertion AssertionID="foo">Some simple text</Assertion></ds:Object></ds:Signature>
\ No newline at end of file
diff --git a/src/test/resources/org/apache/xml/security/samples/input/eddsa.p12 b/src/test/resources/org/apache/xml/security/samples/input/eddsa.p12
new file mode 100644
index 00000000..aaf3b2f2
Binary files /dev/null and b/src/test/resources/org/apache/xml/security/samples/input/eddsa.p12 differ
diff --git a/src/test/resources/org/apache/xml/security/samples/input/eddsaEd25519Signature.xml b/src/test/resources/org/apache/xml/security/samples/input/eddsaEd25519Signature.xml
new file mode 100644
index 00000000..e67158d7
--- /dev/null
+++ b/src/test/resources/org/apache/xml/security/samples/input/eddsaEd25519Signature.xml
@@ -0,0 +1,34 @@
+<!-- Comment before -->
+<RootElement>Some simple text
+<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519"></ds:SignatureMethod>
+<ds:Reference URI="">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
+<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
+<ds:DigestValue>LKyUpNaZJ2joznVzwEup5JDwtS0=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>
+V4fnFoXxWJEJpSr/MnkmAOF5iM/OGeg/f/Vkw+aD+R1BsPZr5voeUKr0Et29WLv51numcRJ9coED
+iQXcoIbLAg==
+</ds:SignatureValue>
+<ds:KeyInfo>
+<ds:X509Data>
+<ds:X509Certificate>
+MIIBezCCAS2gAwIBAgIGAYR2SB6KMAUGAytlcDBSMSMwIQYDVQQDDBpYTUwgRWQyNTUxOSBTaWdu
+YXR1cmUgVGVzdDEWMBQGCgmSJomT8ixkARkWBmFwYWNoZTETMBEGCgmSJomT8ixkARkWA29yZzAe
+Fw0yMjExMTQxMzE1NDhaFw0yNjExMTQxMzE1NDhaMFIxIzAhBgNVBAMMGlhNTCBFZDI1NTE5IFNp
+Z25hdHVyZSBUZXN0MRYwFAYKCZImiZPyLGQBGRYGYXBhY2hlMRMwEQYKCZImiZPyLGQBGRYDb3Jn
+MCowBQYDK2VwAyEAhxvsjkHukjJDs7Z8NvUNUChup4RKpkfTMPRnseY+SwyjIzAhMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMAUGAytlcANBALRvL/aEAn9WWtPpseszszSWR3Gyn5IS
+qgXKtWbiZIMUTvF7QU8MgkXK8s329fPLCb8+6kvE6K24bxVWpabEEgs=
+</ds:X509Certificate>
+</ds:X509Data>
+</ds:KeyInfo>
+</ds:Signature></RootElement>
+<!-- Comment after -->
\ No newline at end of file
diff --git a/src/test/resources/org/apache/xml/security/samples/input/eddsaEd448Signature.xml b/src/test/resources/org/apache/xml/security/samples/input/eddsaEd448Signature.xml
new file mode 100644
index 00000000..f4d9c6d0
--- /dev/null
+++ b/src/test/resources/org/apache/xml/security/samples/input/eddsaEd448Signature.xml
@@ -0,0 +1,35 @@
+<!-- Comment before -->
+<RootElement>Some simple text
+<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
+<ds:SignedInfo>
+<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"></ds:CanonicalizationMethod>
+<ds:SignatureMethod Algorithm="http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"></ds:SignatureMethod>
+<ds:Reference URI="">
+<ds:Transforms>
+<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"></ds:Transform>
+<ds:Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments"></ds:Transform>
+</ds:Transforms>
+<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"></ds:DigestMethod>
+<ds:DigestValue>LKyUpNaZJ2joznVzwEup5JDwtS0=</ds:DigestValue>
+</ds:Reference>
+</ds:SignedInfo>
+<ds:SignatureValue>
+akkDnnKP8IH2lupCxXPW/l+s/L259MUgd3hTjFY9tg9SUlcQhyG48mZvZh6eh870IvFy/0z30hYA
+HDXW5ZuqvgrF4voKqBrs9WWsIwXMXTUWhzelrEaL4PGgGmeNfi9d+r9lsNtpuhCg7c9nAU4wTjUA
+</ds:SignatureValue>
+<ds:KeyInfo>
+<ds:X509Data>
+<ds:X509Certificate>
+MIIBwjCCAUKgAwIBAgIGAYR2SB8kMAUGAytlcTBQMSEwHwYDVQQDDBhYTUwgRWQ0NDggU2lnbmF0
+dXJlIFRlc3QxFjAUBgoJkiaJk/IsZAEZFgZhcGFjaGUxEzARBgoJkiaJk/IsZAEZFgNvcmcwHhcN
+MjIxMTE0MTMxNTQ4WhcNMjYxMTE0MTMxNTQ4WjBQMSEwHwYDVQQDDBhYTUwgRWQ0NDggU2lnbmF0
+dXJlIFRlc3QxFjAUBgoJkiaJk/IsZAEZFgZhcGFjaGUxEzARBgoJkiaJk/IsZAEZFgNvcmcwQzAF
+BgMrZXEDOgBSokK9a5+Bpmi4vZkdhdvKDJK6AfR5aBo95bEqrdNGli+s+0iTsVvLptAvSNZu2xQK
+88rbOTbGVACjIzAhMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGmMAUGAytlcQNzAF2v
+bxSz55R+nN3FDZKuu/Yhq/jEfjH9i7aAwB0HSKqqq3RiPKl48F1ER7kYwDJjZYmj0SXdCzqZgFVN
+dCb6GgrdFIqxg+DHqfoQ+tM+fvhpkkydTtAvKcUX8xspuQ8C2jv39OzEH2ONzMdtWjjS4H4ZAA==
+</ds:X509Certificate>
+</ds:X509Data>
+</ds:KeyInfo>
+</ds:Signature></RootElement>
+<!-- Comment after -->
\ No newline at end of file