diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index c6a7f0d8115..92bde0749ce 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -1001,6 +1001,23 @@ jdk.xml.dsig.secureValidationPolicy=\ noDuplicateIds,\ noRetrievalMethodLoops +# +# Support for the here() function +# +# This security property determines whether the here() XPath function is +# supported in XML Signature generation and verification. +# +# If this property is set to false, the here() function is not supported. +# Generating an XML Signature that uses the here() function will throw an +# XMLSignatureException. Validating an existing XML Signature that uses the +# here() function will also throw an XMLSignatureException. +# +# The default value for this property is true. +# +# Note: This property is currently used by the JDK Reference implementation. +# It is not guaranteed to be examined and used by other implementations. +# +#jdk.xml.dsig.hereFunctionSupported=true # # Deserialization JVM-wide filter factory diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy index 6735205d690..86d45147709 100644 --- a/src/java.base/share/lib/security/default.policy +++ b/src/java.base/share/lib/security/default.policy @@ -96,6 +96,8 @@ grant codeBase "jrt:/java.xml.crypto" { "removeProviderProperty.XMLDSig"; permission java.security.SecurityPermission "com.sun.org.apache.xml.internal.security.register"; + permission java.security.SecurityPermission + "getProperty.jdk.xml.dsig.hereFunctionSupported"; permission java.security.SecurityPermission "getProperty.jdk.xml.dsig.secureValidationPolicy"; permission java.lang.RuntimePermission diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java index 46a265da6f1..5483f02f127 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/JCEMapper.java @@ -209,6 +209,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/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java index 750692f2e9b..0c984d4e030 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/SignatureAlgorithm.java @@ -31,10 +31,7 @@ import java.security.spec.AlgorithmParameterSpec; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; -import com.sun.org.apache.xml.internal.security.algorithms.implementations.IntegrityHmac; -import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureBaseRSA; -import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureDSA; -import com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA; +import com.sun.org.apache.xml.internal.security.algorithms.implementations.*; import com.sun.org.apache.xml.internal.security.exceptions.AlgorithmAlreadyRegisteredException; import com.sun.org.apache.xml.internal.security.exceptions.XMLSecurityException; import com.sun.org.apache.xml.internal.security.signature.XMLSignature; @@ -496,6 +493,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/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java index 63449eee9bb..510fab21584 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/ECDSAUtils.java @@ -30,7 +30,6 @@ import java.math.BigInteger; import java.security.interfaces.ECPublicKey; import java.security.spec.*; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; public final class ECDSAUtils { @@ -786,9 +785,7 @@ public final class ECDSAUtils { field = ecFieldF2m.getReductionPolynomial(); } - Iterator ecCurveDefinitionIterator = ecCurveDefinitions.iterator(); - while (ecCurveDefinitionIterator.hasNext()) { - ECCurveDefinition ecCurveDefinition = ecCurveDefinitionIterator.next(); + for (ECCurveDefinition ecCurveDefinition : ecCurveDefinitions) { String oid = ecCurveDefinition.equals(field, a, b, affineX, affineY, order, h); if (oid != null) { return oid; @@ -798,9 +795,7 @@ public final class ECDSAUtils { } public static ECCurveDefinition getECCurveDefinition(String oid) { - Iterator ecCurveDefinitionIterator = ecCurveDefinitions.iterator(); - while (ecCurveDefinitionIterator.hasNext()) { - ECCurveDefinition ecCurveDefinition = ecCurveDefinitionIterator.next(); + for (ECCurveDefinition ecCurveDefinition : ecCurveDefinitions) { if (ecCurveDefinition.getOid().equals(oid)) { return ecCurveDefinition; } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureEDDSA.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureEDDSA.java new file mode 100644 index 00000000000..03eb36e076c --- /dev/null +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/algorithms/implementations/SignatureEDDSA.java @@ -0,0 +1,228 @@ +/* + * reserved comment block + * DO NOT REMOVE OR ALTER! + */ +/** + * 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 com.sun.org.apache.xml.internal.security.algorithms.implementations; + +import com.sun.org.apache.xml.internal.security.algorithms.JCEMapper; +import com.sun.org.apache.xml.internal.security.algorithms.SignatureAlgorithmSpi; +import com.sun.org.apache.xml.internal.security.signature.XMLSignature; +import com.sun.org.apache.xml.internal.security.signature.XMLSignatureException; +import com.sun.org.apache.xml.internal.security.utils.XMLUtils; + +import java.io.IOException; +import java.security.*; +import java.security.spec.AlgorithmParameterSpec; + +/** + * + */ +public abstract class SignatureEDDSA extends SignatureAlgorithmSpi { + + private static final com.sun.org.slf4j.internal.Logger LOG = + com.sun.org.slf4j.internal.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/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java index ce971a45a98..d57a947dc0d 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/CanonicalizerBase.java @@ -27,7 +27,6 @@ import java.io.OutputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -458,13 +457,17 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { } while(true); } - protected int isVisibleDO(Node currentNode, int level) { + protected int isVisibleDO(Node currentNode, int level) + throws CanonicalizationException { if (nodeFilter != null) { - Iterator it = nodeFilter.iterator(); - while (it.hasNext()) { - int i = it.next().isNodeIncludeDO(currentNode, level); - if (i != 1) { - return i; + for (NodeFilter filter : nodeFilter) { + try { + int i = filter.isNodeIncludeDO(currentNode, level); + if (i != 1) { + return i; + } + } catch (Exception e) { + throw new CanonicalizationException(e); } } } @@ -474,13 +477,17 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { return 1; } - protected int isVisibleInt(Node currentNode) { + protected int isVisibleInt(Node currentNode) + throws CanonicalizationException { if (nodeFilter != null) { - Iterator it = nodeFilter.iterator(); - while (it.hasNext()) { - int i = it.next().isNodeInclude(currentNode); - if (i != 1) { - return i; + for (NodeFilter filter : nodeFilter) { + try { + int i = filter.isNodeInclude(currentNode); + if (i != 1) { + return i; + } + } catch (Exception e) { + throw new CanonicalizationException(e); } } } @@ -490,12 +497,15 @@ public abstract class CanonicalizerBase extends CanonicalizerSpi { return 1; } - protected boolean isVisible(Node currentNode) { + protected boolean isVisible(Node currentNode) throws CanonicalizationException { if (nodeFilter != null) { - Iterator it = nodeFilter.iterator(); - while (it.hasNext()) { - if (it.next().isNodeInclude(currentNode) != 1) { - return false; + for (NodeFilter filter : nodeFilter) { + try { + if (filter.isNodeInclude(currentNode) != 1) { + return false; + } + } catch (Exception e) { + throw new CanonicalizationException(e); } } } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java index f0b1903accd..2ffe6805957 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/NameSpaceSymbTable.java @@ -24,7 +24,6 @@ package com.sun.org.apache.xml.internal.security.c14n.implementations; import java.util.ArrayList; import java.util.Collection; -import java.util.Iterator; import java.util.List; @@ -50,7 +49,7 @@ public class NameSpaceSymbTable { initialMap.put(XMLNS, ne); } - /**The map betwen prefix-> entry table. */ + /**The map between prefix-> entry table. */ private SymbMap symb; /**The stacks for removing the definitions when doing pop.*/ @@ -58,7 +57,7 @@ public class NameSpaceSymbTable { private boolean cloned = true; /** - * Default constractor + * Default constructor **/ public NameSpaceSymbTable() { //Insert the default binding for xmlns. @@ -75,9 +74,7 @@ public class NameSpaceSymbTable { * @param result the list where to fill the unrendered xmlns definitions. **/ public void getUnrenderedNodes(Collection result) { - Iterator it = symb.entrySet().iterator(); - while (it.hasNext()) { - NameSpaceSymbEntry n = it.next(); + for (NameSpaceSymbEntry n : symb.entrySet()) { //put them rendered? if (!n.rendered && n.n != null) { n = n.clone(); @@ -170,14 +167,14 @@ public class NameSpaceSymbTable { symb.put(prefix, entry); entry.rendered = true; entry.lastrendered = entry.uri; - // Return the node for outputing. + // Return the node for outputting. return entry.n; } /** * Gets a definition without mark it as render. * For render in exclusive c14n the namespaces in the include prefixes. - * @param prefix The prefix whose definition is neaded. + * @param prefix The prefix whose definition is needed. * @return the attr to render, null if there is no need to render **/ public Attr getMappingWithoutRendered(String prefix) { diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/XmlAttrStack.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/XmlAttrStack.java index 71b84139bee..a636a777868 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/XmlAttrStack.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/c14n/implementations/XmlAttrStack.java @@ -129,20 +129,16 @@ class XmlAttrStack { } } if (!baseAttrs.isEmpty()) { - Iterator it = col.iterator(); String base = null; Attr baseAttr = null; - while (it.hasNext()) { - Attr n = it.next(); + for (Attr n : col) { if ("base".equals(n.getLocalName())) { base = n.getValue(); baseAttr = n; break; } } - it = baseAttrs.iterator(); - while (it.hasNext()) { - Attr n = it.next(); + for (Attr n : baseAttrs) { if (base == null) { base = n.getValue(); baseAttr = n; @@ -162,9 +158,7 @@ class XmlAttrStack { } else { for (; size >= 0; size--) { e = levels.get(size); - Iterator it = e.nodes.iterator(); - while (it.hasNext()) { - Attr n = it.next(); + for (Attr n : e.nodes) { if (!loa.containsKey(n.getName())) { loa.put(n.getName(), n); } @@ -352,7 +346,7 @@ class XmlAttrStack { // that from the input buffer else if the input buffer consists // only of ".." and if the output buffer does not contain only // the root slash "/", then move the ".." to the output buffer - // else delte it.; otherwise, + // else delete it.; otherwise, } else if (".".equals(input)) { input = ""; printStep("2D", output.toString(), input); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/MgmtData.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/MgmtData.java index b76ec1ecc5b..53fcf0f8954 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/MgmtData.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/content/MgmtData.java @@ -59,7 +59,7 @@ public class MgmtData extends SignatureElementProxy implements KeyInfoContent { /** * Method getMgmtData * - * @return the managment data + * @return the management data */ public String getMgmtData() { return this.getTextFromTextChild(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java index 3683ddb406d..c3170fe2fa1 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/keys/keyresolver/implementations/RetrievalMethodResolver.java @@ -31,7 +31,6 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; import java.util.ListIterator; import java.util.Set; @@ -283,10 +282,8 @@ public class RetrievalMethodResolver extends KeyResolverSpi { } private static Element getDocumentElement(Set set) { - Iterator it = set.iterator(); Element e = null; - while (it.hasNext()) { - Node currentNode = it.next(); + for (Node currentNode : set) { if (currentNode != null && Node.ELEMENT_NODE == currentNode.getNodeType()) { e = (Element) currentNode; break; @@ -294,7 +291,7 @@ public class RetrievalMethodResolver extends KeyResolverSpi { } List parents = new ArrayList<>(); - // Obtain all the parents of the elemnt + // Obtain all the parents of the element while (e != null) { parents.add(e); Node n = e.getParentNode(); diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml index ed87c833c1e..b787fe54b07 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/resource/config.xml @@ -128,6 +128,11 @@ JAVACLASS="com.sun.org.apache.xml.internal.security.algorithms.implementations.SignatureECDSA$SignatureECDSASHA512" /> + + + diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java index 285d87e0a6d..9d0ac02d75e 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/Manifest.java @@ -28,7 +28,6 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; @@ -357,11 +356,8 @@ public class Manifest extends SignatureElementProxy { currentRef.dereferenceURIandPerformTransforms(null); Set nl = signedManifestNodes.getNodeSet(); Manifest referencedManifest = null; - Iterator nlIterator = nl.iterator(); - - while (nlIterator.hasNext()) { - Node n = nlIterator.next(); + for (Node n : nl) { if (n.getNodeType() == Node.ELEMENT_NODE && ((Element) n).getNamespaceURI().equals(Constants.SignatureSpecNS) && ((Element) n).getLocalName().equals(Constants._TAG_MANIFEST) diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/NodeFilter.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/NodeFilter.java index 7b901ec6f6b..e53dda34f4d 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/NodeFilter.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/NodeFilter.java @@ -22,6 +22,7 @@ */ package com.sun.org.apache.xml.internal.security.signature; +import com.sun.org.apache.xml.internal.security.transforms.TransformationException; import org.w3c.dom.Node; /** @@ -37,7 +38,7 @@ public interface NodeFilter { * -1 if the node and all it's child must not be output. * */ - int isNodeInclude(Node n); + int isNodeInclude(Node n) throws TransformationException; /** * Tells if a node must be output in a c14n. @@ -50,6 +51,6 @@ public interface NodeFilter { * 0 if node must not be output, * -1 if the node and all it's child must not be output. */ - int isNodeIncludeDO(Node n, int level); + int isNodeIncludeDO(Node n, int level) throws TransformationException; } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/ObjectContainer.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/ObjectContainer.java index cf515b8709b..5ab6c361643 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/ObjectContainer.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/ObjectContainer.java @@ -34,7 +34,7 @@ import org.w3c.dom.Node; * Handles {@code <ds:Object>} elements * {@code Object} {@link Element} supply facility which can contain any kind data * - * $todo$ if we remove childen, the boolean values are not updated + * $todo$ if we remove children, the boolean values are not updated */ public class ObjectContainer extends SignatureElementProxy { diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperty.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperty.java index be83a2a9ca9..1929f126a14 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperty.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/SignatureProperty.java @@ -49,7 +49,7 @@ public class SignatureProperty extends SignatureElementProxy { } /** - * Constructs {@link SignatureProperty} using sepcified {@code target} attribute and + * Constructs {@link SignatureProperty} using specified {@code target} attribute and * {@code id} attribute * * @param doc the {@link Document} in which {@code XMLsignature} is placed diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java index df9e3014669..b2254cff581 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/VerifiedReference.java @@ -38,7 +38,7 @@ public class VerifiedReference { * @param valid Whether this Reference was successfully validated or not * @param uri The URI of this Reference * @param manifestReferences If this reference is a reference to a Manifest, this holds the list - * of verified referenes associated with this Manifest + * of verified references associated with this Manifest */ public VerifiedReference(boolean valid, String uri, List manifestReferences) { this.valid = valid; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java index e9cdaa1a1d9..dff41c30e51 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignature.java @@ -201,6 +201,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/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInputDebugger.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInputDebugger.java index 45c2508946d..193bd207867 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInputDebugger.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/signature/XMLSignatureInputDebugger.java @@ -127,7 +127,7 @@ public class XMLSignatureInputDebugger { /** * Constructor XMLSignatureInputDebugger * - * @param xmlSignatureInput the signatur to pretty print + * @param xmlSignatureInput the signature to pretty print * @param inclusiveNamespace */ public XMLSignatureInputDebugger( diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java index 55544466575..f227ba2cc1c 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/Transform.java @@ -309,7 +309,7 @@ public final class Transform extends SignatureElementProxy { /** * Transforms the input, and generates {@link XMLSignatureInput} as output. * - * @param input input {@link XMLSignatureInput} which can supplied Octect + * @param input input {@link XMLSignatureInput} which can supplied Octet * Stream and NodeSet as Input of Transformation * @param os where to output the result of the last transformation * @param secureValidation Whether secure validation is enabled diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java index ca844c00682..72dd114defb 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath.java @@ -20,10 +20,16 @@ * specific language governing permissions and limitations * under the License. */ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + */ package com.sun.org.apache.xml.internal.security.transforms.implementations; import java.io.IOException; import java.io.OutputStream; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.security.Security; import javax.xml.transform.TransformerException; @@ -33,10 +39,7 @@ import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; import com.sun.org.apache.xml.internal.security.transforms.TransformationException; import com.sun.org.apache.xml.internal.security.transforms.Transforms; -import com.sun.org.apache.xml.internal.security.utils.Constants; -import com.sun.org.apache.xml.internal.security.utils.XMLUtils; -import com.sun.org.apache.xml.internal.security.utils.XPathAPI; -import com.sun.org.apache.xml.internal.security.utils.XPathFactory; +import com.sun.org.apache.xml.internal.security.utils.*; import org.w3c.dom.DOMException; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -52,8 +55,25 @@ import org.w3c.dom.Node; */ public class TransformXPath extends TransformSpi { - private static final com.sun.org.slf4j.internal.Logger LOG = - com.sun.org.slf4j.internal.LoggerFactory.getLogger(TransformXPath.class); + // Whether the here() XPath function is supported. + static final boolean HEREFUNC; + + static { + @SuppressWarnings("removal") + String prop = + AccessController.doPrivileged((PrivilegedAction) () -> + Security.getProperty("jdk.xml.dsig.hereFunctionSupported")); + if (prop == null) { + HEREFUNC = true; // default true + } else if (prop.equals("true")) { + HEREFUNC = true; + } else if (prop.equals("false")) { + HEREFUNC = false; + } else { + throw new IllegalArgumentException( + "Invalid jdk.xml.dsig.hereFunctionSupported setting: " + prop); + } + } /** * {@inheritDoc} @@ -112,7 +132,9 @@ public class TransformXPath extends TransformSpi { } protected XPathFactory getXPathFactory() { - return XPathFactory.newInstance(); + return HEREFUNC + ? XPathFactory.newInstance() + : new JDKXPathFactory(); } /** @@ -140,20 +162,19 @@ public class TransformXPath extends TransformSpi { /** * @see com.sun.org.apache.xml.internal.security.signature.NodeFilter#isNodeInclude(org.w3c.dom.Node) */ - public int isNodeInclude(Node currentNode) { + public int isNodeInclude(Node currentNode) throws TransformationException { try { boolean include = xPathAPI.evaluate(currentNode, xpathnode, str, xpathElement); if (include) { return 1; } return 0; - } catch (TransformerException e) { - LOG.debug("Error evaluating XPath expression", e); - return 0; + } catch (TransformerException ex) { + throw new TransformationException(ex); } } - public int isNodeIncludeDO(Node n, int level) { + public int isNodeIncludeDO(Node n, int level) throws TransformationException { return isNodeInclude(n); } diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java index 800f7cae36d..b198c541c21 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/transforms/implementations/TransformXPath2Filter.java @@ -38,6 +38,7 @@ import com.sun.org.apache.xml.internal.security.transforms.TransformSpi; import com.sun.org.apache.xml.internal.security.transforms.TransformationException; import com.sun.org.apache.xml.internal.security.transforms.Transforms; import com.sun.org.apache.xml.internal.security.transforms.params.XPath2FilterContainer; +import com.sun.org.apache.xml.internal.security.utils.JDKXPathFactory; import com.sun.org.apache.xml.internal.security.utils.XMLUtils; import com.sun.org.apache.xml.internal.security.utils.XPathAPI; import com.sun.org.apache.xml.internal.security.utils.XPathFactory; @@ -94,7 +95,9 @@ public class TransformXPath2Filter extends TransformSpi { inputDoc = XMLUtils.getOwnerDocument(input.getNodeSet()); } - XPathFactory xpathFactory = XPathFactory.newInstance(); + XPathFactory xpathFactory = TransformXPath.HEREFUNC + ? XPathFactory.newInstance() + : new JDKXPathFactory(); for (int i = 0; i < xpathElements.length; i++) { Element xpathElement = xpathElements[i]; diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java index d2d63fc85ff..6111cbeb804 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/I18n.java @@ -55,7 +55,7 @@ public final class I18n { /** * Method translate * - * translates a message ID into an internationalized String, see alse + * translates a message ID into an internationalized String, see also * {@code XMLSecurityException.getExceptionMEssage()}. The strings are * stored in the {@code ResourceBundle}, which is identified in * {@code exceptionMessagesResourceBundleBase} diff --git a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java index 552d1330a3f..1f0fc29fbb4 100644 --- a/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java +++ b/src/java.xml.crypto/share/classes/com/sun/org/apache/xml/internal/security/utils/RFC2253Parser.java @@ -468,15 +468,15 @@ public class RFC2253Parser { */ static String trim(String str) { - String trimed = str.trim(); - int i = str.indexOf(trimed) + trimed.length(); + String trimmed = str.trim(); + int i = str.indexOf(trimmed) + trimmed.length(); - if (str.length() > i && trimed.endsWith("\\") - && !trimed.endsWith("\\\\") && str.charAt(i) == ' ') { - trimed = trimed + " "; + if (str.length() > i && trimmed.endsWith("\\") + && !trimmed.endsWith("\\\\") && str.charAt(i) == ' ') { + trimmed = trimmed + " "; } - return trimed; + return trimmed; } } diff --git a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/DigestMethod.java b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/DigestMethod.java index e58c435950b..7d7d49d02e9 100644 --- a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/DigestMethod.java +++ b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/DigestMethod.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,7 @@ import java.security.spec.AlgorithmParameterSpec; /** * A representation of the XML DigestMethod element as - * defined in the + * defined in the * W3C Recommendation for XML-Signature Syntax and Processing. * The XML Schema Definition is defined as: *
@@ -51,6 +51,12 @@ import java.security.spec.AlgorithmParameterSpec;
  * A DigestMethod instance may be created by invoking the
  * {@link XMLSignatureFactory#newDigestMethod newDigestMethod} method
  * of the {@link XMLSignatureFactory} class.
+ * 

+ * The digest method algorithm URIs defined in this class are specified + * in the + * W3C Recommendation for XML-Signature Syntax and Processing + * and + * RFC 9231: Additional XML Security Uniform Resource Identifiers (URIs) * * @author Sean Mullan * @author JSR 105 Expert Group @@ -59,8 +65,6 @@ import java.security.spec.AlgorithmParameterSpec; */ public interface DigestMethod extends XMLStructure, AlgorithmMethod { - // All methods can be found in RFC 6931. - /** * The * SHA1 digest method algorithm URI. diff --git a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java index 5459045fec8..6bb1b2d2da0 100644 --- a/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java +++ b/src/java.xml.crypto/share/classes/javax/xml/crypto/dsig/SignatureMethod.java @@ -34,7 +34,7 @@ import java.security.spec.AlgorithmParameterSpec; /** * A representation of the XML SignatureMethod element - * as defined in the + * as defined in the * W3C Recommendation for XML-Signature Syntax and Processing. * The XML Schema Definition is defined as: *

@@ -52,6 +52,12 @@ import java.security.spec.AlgorithmParameterSpec;
  * A SignatureMethod instance may be created by invoking the
  * {@link XMLSignatureFactory#newSignatureMethod newSignatureMethod} method
  * of the {@link XMLSignatureFactory} class.
+ * 

+ * The signature method algorithm URIs defined in this class are specified + * in the + * W3C Recommendation for XML-Signature Syntax and Processing + * and + * RFC 9231: Additional XML Security Uniform Resource Identifiers (URIs) * * @author Sean Mullan * @author JSR 105 Expert Group @@ -60,8 +66,6 @@ import java.security.spec.AlgorithmParameterSpec; */ public interface SignatureMethod extends XMLStructure, AlgorithmMethod { - // All methods can be found in RFC 6931. - /** * The DSA-SHA1 * (DSS) signature method algorithm URI. @@ -255,6 +259,22 @@ public interface SignatureMethod extends XMLStructure, AlgorithmMethod { */ String RSA_PSS = "http://www.w3.org/2007/05/xmldsig-more#rsa-pss"; + /** + * The + * ED25519 signature method algorithm URI. + * + * @since 21 + */ + String ED25519 = "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed25519"; + + /** + * The + * ED448 signature method algorithm URI. + * + * @since 21 + */ + String ED448 = "http://www.w3.org/2021/04/xmldsig-more#eddsa-ed448"; + /** * Returns the algorithm-specific input parameters of this * SignatureMethod. diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java index 8ff9fc7a2bf..4bc0a543117 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/AbstractDOMSignatureMethod.java @@ -49,7 +49,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/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheNodeSetData.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheNodeSetData.java index 2ee5777ef60..b15c8784d5c 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheNodeSetData.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/ApacheNodeSetData.java @@ -31,6 +31,8 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import javax.xml.crypto.NodeSetData; + +import com.sun.org.apache.xml.internal.security.transforms.TransformationException; import org.w3c.dom.Node; import com.sun.org.apache.xml.internal.security.signature.NodeFilter; import com.sun.org.apache.xml.internal.security.signature.XMLSignatureInput; @@ -46,11 +48,11 @@ public class ApacheNodeSetData implements ApacheData, NodeSetData { public Iterator iterator() { // If nodefilters are set, must execute them first to create node-set - if (xi.getNodeFilters() != null && !xi.getNodeFilters().isEmpty()) { - return Collections.unmodifiableSet - (getNodeSet(xi.getNodeFilters())).iterator(); - } try { + if (xi.getNodeFilters() != null && !xi.getNodeFilters().isEmpty()) { + return Collections.unmodifiableSet + (getNodeSet(xi.getNodeFilters())).iterator(); + } return Collections.unmodifiableSet(xi.getNodeSet()).iterator(); } catch (Exception e) { // should not occur @@ -63,7 +65,8 @@ public class ApacheNodeSetData implements ApacheData, NodeSetData { return xi; } - private Set getNodeSet(List nodeFilters) { + private Set getNodeSet(List nodeFilters) + throws TransformationException { if (xi.isNeedsToBeExpanded()) { XMLUtils.circumventBug2650 (XMLUtils.getOwnerDocument(xi.getSubNode())); diff --git a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java index 98cf1772fe8..267e29d901d 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMSignatureMethod.java @@ -82,6 +82,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"; @@ -220,6 +226,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); @@ -542,6 +552,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 { @@ -1021,4 +1064,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/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java index 19f842f4429..5ee0f78a053 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/DOMXMLSignatureFactory.java @@ -302,6 +302,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/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java index 65bb25f058f..f169a44391c 100644 --- a/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java +++ b/src/java.xml.crypto/share/classes/org/jcp/xml/dsig/internal/dom/XMLDSigRI.java @@ -134,7 +134,7 @@ public final class XMLDSigRI extends Provider { @SuppressWarnings("removal") public XMLDSigRI() { // This is the JDK XMLDSig provider, synced from - // Apache Santuario XML Security for Java, version 2.3.0 + // Apache Santuario XML Security for Java, version 3.0.2 super("XMLDSig", VER, INFO); final Provider p = this; diff --git a/src/java.xml.crypto/share/legal/santuario.md b/src/java.xml.crypto/share/legal/santuario.md index fa87128126d..bee55d85a83 100644 --- a/src/java.xml.crypto/share/legal/santuario.md +++ b/src/java.xml.crypto/share/legal/santuario.md @@ -1,24 +1,7 @@ -## Apache Santuario v2.3.0 - -### Apache Santuario Notice -

-
-  Apache Santuario - XML Security for Java
-  Copyright 1999-2021 The Apache Software Foundation
-
-  This product includes software developed at
-  The Apache Software Foundation (http://www.apache.org/).
-
-  It was originally based on software copyright (c) 2001, Institute for
-  Data Communications Systems, .
-
-  The development of this software was partly funded by the European
-  Commission in the  project in the ISIS Programme.
-
-
+## Apache Santuario v3.0.2 ### Apache 2.0 License -
+```
 
                               Apache License
                         Version 2.0, January 2004
@@ -222,4 +205,23 @@ 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.
 
-
+``` + +### Apache Santuario Notice +``` + +Apache Santuario - XML Security for Java +Copyright 1999-2023 The Apache Software Foundation + +This product includes software developed at +The Apache Software Foundation (http://www.apache.org/). + +It was originally based on software copyright (c) 2001, Institute for +Data Communications Systems, . + +The development of this software was partly funded by the European +Commission in the project in the ISIS Programme. + +This product contains software that is +copyright (c) 2021, Oracle and/or its affiliates. +``` diff --git a/test/jdk/TEST.groups b/test/jdk/TEST.groups index 5631ea6237c..f3f352d4e1e 100644 --- a/test/jdk/TEST.groups +++ b/test/jdk/TEST.groups @@ -213,6 +213,7 @@ jdk_security1 = \ jdk_security2 = \ javax/crypto \ javax/xml/crypto \ + com/sun/org/apache/xml/internal/security \ com/sun/crypto jdk_security3 = \ @@ -220,7 +221,6 @@ jdk_security3 = \ -javax/security/auth/kerberos \ com/sun/security \ -com/sun/security/jgss \ - com/sun/org/apache/xml/internal/security \ jdk/security \ sun/security \ -sun/security/krb5 \ diff --git a/test/jdk/javax/xml/crypto/dsig/Basic.java b/test/jdk/javax/xml/crypto/dsig/Basic.java new file mode 100644 index 00000000000..4c2e6edd36d --- /dev/null +++ b/test/jdk/javax/xml/crypto/dsig/Basic.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.SecurityTools; +import jdk.test.lib.Utils; + +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.security.KeyStore; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.List; + +import static jdk.test.lib.security.XMLUtils.*; +/** + * @test + * @bug 8305972 + * @summary Basic tests using XMLUtils + * @library /test/lib + * @modules java.xml.crypto + */ +public class Basic { + + public static void main(String[] args) throws Exception { + var x = "cx"; + var p = Files.write(Path.of("x.xml"), List.of(x)); + var b = Path.of("").toUri().toString(); + var d = string2doc(x); + var pass = "changeit".toCharArray(); + for (String alg: List.of("DSA", "RSA", "RSASSA-PSS", "EC", "EdDSA", "Ed25519", "Ed448")) { + SecurityTools.keytool(String.format( + "-keystore ks -keyalg %s -storepass changeit -genkeypair -alias %s -dname CN=%s", + alg, alg, alg)).shouldHaveExitValue(0); + var ks = KeyStore.getInstance(new File("ks"), pass); + var c = (X509Certificate) ks.getCertificate(alg); + var pr = (PrivateKey) ks.getKey(alg, pass); + var pu = c.getPublicKey(); + + var s0 = signer(pr); // No KeyInfo + var s1 = signer(pr, c); // KeyInfo is X509Data + var s2 = signer(ks, alg, pass); // KeyInfo is KeyName + var v1 = validator(); // knows nothing + var v2 = validator(ks); // knows KeyName + + Utils.runAndCheckException(() -> v1.validate(s0.sign(d)), IllegalArgumentException.class); // need PublicKey + s0.sign(string2doc(x)); + Asserts.assertTrue(v1.validate(s0.sign(d), pu)); // need PublicKey + Asserts.assertTrue(v1.validate(s1.sign(d))); // can read KeyInfo + Asserts.assertTrue(v2.validate(s2.sign(d))); // can read KeyInfo + Asserts.assertTrue(v2.secureValidation(false).validate(s2.sign(p.toUri()))); // can read KeyInfo + Asserts.assertTrue(v2.secureValidation(false).baseURI(b).validate( + s2.sign(p.toAbsolutePath().getParent().toUri(), p.getFileName().toUri()))); // can read KeyInfo + + Asserts.assertTrue(v1.validate(s0.sign("text"), pu)); // plain text + Asserts.assertTrue(v1.validate(s0.sign("binary".getBytes()), pu)); // raw data + Asserts.assertTrue(v1.validate(s0.signEnveloping(d, "x", "#x"), pu)); + Asserts.assertTrue(v1.validate(s0.signEnveloping(d, "x", "#xpointer(id('x'))"), pu)); + + // No KeyValue defined for RSASSA-PSS or EdDSA yet + if (!alg.startsWith("Ed") && !alg.equals("RSASSA-PSS")) { + var ss = signer(pr, pu); // KeyInfo is PublicKey + Asserts.assertTrue(v1.validate(ss.sign(d))); // can read KeyInfo + Asserts.assertTrue(v1.validate(ss.sign("text"))); // plain text + Asserts.assertTrue(v1.validate(ss.sign("binary".getBytes()))); // raw data + Asserts.assertTrue(v1.validate(ss.signEnveloping(d, "x", "#x"))); + Asserts.assertTrue(v1.validate(ss.signEnveloping(d, "x", "#xpointer(id('x'))"))); + } + } + } + +} diff --git a/test/jdk/javax/xml/crypto/dsig/GenerationTests.java b/test/jdk/javax/xml/crypto/dsig/GenerationTests.java index e78ec024306..53cb147fa1d 100644 --- a/test/jdk/javax/xml/crypto/dsig/GenerationTests.java +++ b/test/jdk/javax/xml/crypto/dsig/GenerationTests.java @@ -24,7 +24,7 @@ /** * @test * @bug 4635230 6283345 6303830 6824440 6867348 7094155 8038184 8038349 8046949 - * 8046724 8079693 8177334 8205507 8210736 8217878 8241306 + * 8046724 8079693 8177334 8205507 8210736 8217878 8241306 8305972 * @summary Basic unit tests for generating XML Signatures with JSR 105 * @modules java.base/sun.security.util * java.base/sun.security.x509 @@ -56,18 +56,8 @@ import java.security.PublicKey; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509CRL; -import java.security.spec.KeySpec; -import java.security.spec.DSAPrivateKeySpec; -import java.security.spec.DSAPublicKeySpec; -import java.security.spec.ECField; -import java.security.spec.ECFieldFp; -import java.security.spec.ECParameterSpec; -import java.security.spec.ECPoint; -import java.security.spec.ECPrivateKeySpec; -import java.security.spec.ECPublicKeySpec; -import java.security.spec.EllipticCurve; -import java.security.spec.RSAPrivateKeySpec; -import java.security.spec.RSAPublicKeySpec; +import java.security.cert.X509Certificate; +import java.security.spec.*; import java.util.*; import java.util.stream.Stream; import javax.crypto.KeyGenerator; @@ -110,12 +100,14 @@ public class GenerationTests { rsaSha1, rsaSha224, rsaSha256, rsaSha384, rsaSha512, ecdsaSha1, ecdsaSha224, ecdsaSha256, ecdsaSha384, ecdsaSha512, hmacSha1, hmacSha224, hmacSha256, hmacSha384, hmacSha512, - rsaSha1mgf1, rsaSha224mgf1, rsaSha256mgf1, rsaSha384mgf1, rsaSha512mgf1, rsaShaPSS; + rsaSha1mgf1, rsaSha224mgf1, rsaSha256mgf1, rsaSha384mgf1, rsaSha512mgf1, + rsaShaPSS, ed25519, ed448; private static DigestMethod sha1, sha224, sha256, sha384, sha512, sha3_224, sha3_256, sha3_384, sha3_512; private static KeyInfo dsa1024, dsa2048, rsa, rsa1024, rsa2048, - p256ki, p384ki, p521ki; + p256ki, p384ki, p521ki, ed25519ki, ed448ki; private static KeySelector kvks = new KeySelectors.KeyValueKeySelector(); + private static KeySelector x5ks = new KeySelectors.RawX509KeySelector(); private static KeySelector sks; private static Key signingKey; private static PublicKey validatingKey; @@ -217,7 +209,8 @@ public class GenerationTests { SignatureMethod.ECDSA_SHA256, SignatureMethod.HMAC_SHA256, SignatureMethod.SHA256_RSA_MGF1, - SignatureMethod.RSA_PSS); + SignatureMethod.RSA_PSS, + SignatureMethod.ED25519); private static final String[] allSignatureMethods = Stream.of(SignatureMethod.class.getDeclaredFields()) @@ -251,7 +244,7 @@ public class GenerationTests { // As of JDK 17, the number of defined algorithms are... static { - if (allSignatureMethods.length != 23 + if (allSignatureMethods.length != 25 || allDigestMethods.length != 9) { System.out.println(Arrays.toString(allSignatureMethods)); System.out.println(Arrays.toString(allDigestMethods)); @@ -312,6 +305,8 @@ public class GenerationTests { test_create_signature_enveloping_p256_sha512(); test_create_signature_enveloping_p384_sha1(); test_create_signature_enveloping_p521_sha1(); + test_create_signature_enveloping_ed25519(); + test_create_signature_enveloping_ed448(); test_create_signature_external_b64_dsa(); test_create_signature_external_dsa(); test_create_signature_keyname(); @@ -359,8 +354,10 @@ public class GenerationTests { Arrays.stream(xml_transforms).forEach(t -> Arrays.stream(KeyInfoType.values()).forEach(k -> { if (isMajor(s, d)) { - test_create_detached_signature(c, s, d, t, k, - Content.Xml, server.getPort(), false, null); + if (!s.contains("#eddsa") || k != KeyInfoType.KeyValue) { + test_create_detached_signature(c, s, d, t, k, + Content.Xml, server.getPort(), false, null); + } } }))))); @@ -370,8 +367,10 @@ public class GenerationTests { Arrays.stream(allDigestMethods).forEach(d -> Arrays.stream(KeyInfoType.values()).forEach(k -> { if (isMajor(s, d)) { - test_create_detached_signature(c, s, d, null, k, - Content.Text, server.getPort(), false, null); + if (!s.contains("#eddsa") || k != KeyInfoType.KeyValue) { + test_create_detached_signature(c, s, d, null, k, + Content.Text, server.getPort(), false, null); + } } })))); @@ -382,9 +381,11 @@ public class GenerationTests { Arrays.stream(non_xml_transforms).forEach(t -> Arrays.stream(KeyInfoType.values()).forEach(k -> { if (isMajor(s, d)) { - test_create_detached_signature(c, s, d, t, k, - Content.Base64, server.getPort(), - false, null); + if (!s.contains("#eddsa") || k != KeyInfoType.KeyValue) { + test_create_detached_signature(c, s, d, t, k, + Content.Base64, server.getPort(), + false, null); + } } }))))); @@ -525,6 +526,11 @@ public class GenerationTests { p521ki = kifac.newKeyInfo(Collections.singletonList (kifac.newKeyValue(getECPublicKey("P521")))); + ed25519ki = kifac.newKeyInfo(Collections.singletonList + (kifac.newX509Data(List.of(getEd25519Certificate())))); + ed448ki = kifac.newKeyInfo(Collections.singletonList + (kifac.newX509Data(List.of(getEd448Certificate())))); + rsaSha1 = fac.newSignatureMethod(SignatureMethod.RSA_SHA1, null); rsaSha224 = fac.newSignatureMethod(SignatureMethod.RSA_SHA224, null); rsaSha256 = fac.newSignatureMethod(SignatureMethod.RSA_SHA256, null); @@ -544,6 +550,9 @@ public class GenerationTests { ecdsaSha384 = fac.newSignatureMethod(SignatureMethod.ECDSA_SHA384, null); ecdsaSha512 = fac.newSignatureMethod(SignatureMethod.ECDSA_SHA512, null); + ed25519 = fac.newSignatureMethod(SignatureMethod.ED25519, null); + ed448 = fac.newSignatureMethod(SignatureMethod.ED448, null); + hmacSha1 = fac.newSignatureMethod(SignatureMethod.HMAC_SHA1, null); hmacSha224 = fac.newSignatureMethod(SignatureMethod.HMAC_SHA224, null); hmacSha256 = fac.newSignatureMethod(SignatureMethod.HMAC_SHA256, null); @@ -855,6 +864,20 @@ public class GenerationTests { System.out.println(); } + static void test_create_signature_enveloping_ed25519() throws Exception { + System.out.println("* Generating signature-enveloping-ed25519.xml"); + test_create_signature_enveloping(sha1, ed25519, ed25519ki, + getEd25519PrivateKey(), x5ks, false, true); + System.out.println(); + } + + static void test_create_signature_enveloping_ed448() throws Exception { + System.out.println("* Generating signature-enveloping-ed448.xml"); + test_create_signature_enveloping(sha1, ed448, ed448ki, + getEd448PrivateKey(), x5ks, false, true); + System.out.println(); + } + static void test_create_signature_external_b64_dsa() throws Exception { System.out.println("* Generating signature-external-b64-dsa.xml"); test_create_signature_external(dsaSha1, dsa1024, signingKey, kvks, true); @@ -1957,6 +1980,8 @@ public class GenerationTests { } else if (sm.contains("#ecdsa-")) { kpg = KeyPairGenerator.getInstance("EC"); kpg.initialize(256); + } else if (sm.contains("#eddsa-")) { + kpg = KeyPairGenerator.getInstance(sm.substring(sm.lastIndexOf('-') + 1)); } else { throw new RuntimeException("Unsupported signature algorithm"); } @@ -2085,6 +2110,20 @@ public class GenerationTests { 1 ); + private static final String ED25519_CERT = + "3081d730818aa003020102020822bc4997b1893265300506032b657030123110300e0603550403130745643235353139301e170d3233303431333033303732365a170d3433303430383033303" + + "732365a30123110300e0603550403130745643235353139302a300506032b657003210012ecd7383ac90c30035dc531285bdb897faafddfc6969271c2ebd9a82b6078e5300506032b65700341" + + "00a3cb7c03bbb3e9fa92eaf3f9a6f2608460d472c6a6ce3bebf0f57f45612e87ebdc6aa6d7527ae9e86c8e10bcccf98963f9b082c0bb44adb240c5fce9bb68b301"; + private static final String ED25519_KEY = + "b59e57e352fa03b3a643946ae60b7f1e276f9ab41f25accaa63b660ba36168b2"; + private static final String ED448_CERT = + "3082011f3081a0a003020102020900ceaefd75473d52b2300506032b65713010310e300c060355040313054564343438301e170d3233303431333033303735345a170d3433303430383033303" + + "735345a3010310e300c0603550403130545643434383043300506032b6571033a00d605be958f21faf6a1181fa96ebe8580cca3cae9b48dfad5145ee999d9df4ef77c355d33ae8b21e9a3541f" + + "b985ae366b9678db1a3fd1fd5c00300506032b65710373000b4dc8de20b261f5ca7cf41777725a2ec6cd107d6b75cd6ad02c00af8096ecf97c7445596aabd70381ce087d2b3b280ca4181566b" + + "9230fd6801e22e53f1514989bc5b06cfb5f7cac222ea9a37a0771a3f7cfcbfd1ba9546bbe333d37ee81c3a53d86247d377225114e1e81123f947a391800"; + private static final String ED448_KEY = + "50b72f081f7f2f3383c4b03975cf49a76ba8b17dec51eaea3cd267b6989b81786e8dd8af4df305eaad60bdd24345b8490548c371d62e926f80"; + private static ECParameterSpec initECParams( String sfield, String a, String b, String gx, String gy, String n, int h) { @@ -2158,6 +2197,16 @@ public class GenerationTests { return kf.generatePublic(kspec); } + private static X509Certificate getEd25519Certificate() throws Exception { + return (X509Certificate) CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(HexFormat.of().parseHex(ED25519_CERT))); + } + + private static X509Certificate getEd448Certificate() throws Exception { + return (X509Certificate) CertificateFactory.getInstance("X.509") + .generateCertificate(new ByteArrayInputStream(HexFormat.of().parseHex(ED448_CERT))); + } + private static PrivateKey getPrivateKey(String algo, int keysize) throws Exception { KeyFactory kf = KeyFactory.getInstance(algo); @@ -2211,6 +2260,16 @@ public class GenerationTests { return kf.generatePrivate(kspec); } + private static PrivateKey getEd25519PrivateKey() throws Exception { + return KeyFactory.getInstance("Ed25519").generatePrivate(new EdECPrivateKeySpec( + NamedParameterSpec.ED25519, HexFormat.of().parseHex(ED25519_KEY))); + } + + private static PrivateKey getEd448PrivateKey() throws Exception { + return KeyFactory.getInstance("Ed448").generatePrivate(new EdECPrivateKeySpec( + NamedParameterSpec.ED448, HexFormat.of().parseHex(ED448_KEY))); + } + private static SecretKey getSecretKey(final byte[] secret) { return new SecretKey() { public String getFormat() { return "RAW"; } diff --git a/test/jdk/javax/xml/crypto/dsig/HereFunction.java b/test/jdk/javax/xml/crypto/dsig/HereFunction.java new file mode 100644 index 00000000000..4910d0e6a89 --- /dev/null +++ b/test/jdk/javax/xml/crypto/dsig/HereFunction.java @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * @test + * @bug 8305972 + * @summary Demonstrate here() support for validating XML Signatures + * @modules java.base/sun.security.util + * java.base/sun.security.x509 + * java.xml.crypto/org.jcp.xml.dsig.internal.dom + * @library /test/lib + * @compile -XDignore.symbol.file KeySelectors.java SignatureValidator.java + * X509KeySelector.java ValidationTests.java + * @run main/othervm HereFunction default true + * @run main/othervm HereFunction true true + * @run main/othervm HereFunction false false + */ +import java.io.File; +import java.io.FileInputStream; +import java.security.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import javax.xml.crypto.Data; +import javax.xml.crypto.KeySelector; +import javax.xml.crypto.OctetStreamData; +import javax.xml.crypto.URIDereferencer; +import javax.xml.crypto.URIReference; +import javax.xml.crypto.URIReferenceException; +import javax.xml.crypto.XMLCryptoContext; +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.spec.C14NMethodParameterSpec; +import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec; +import javax.xml.parsers.DocumentBuilderFactory; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.security.SecurityUtils; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.NodeList; + +public class HereFunction { + + private final static String DIR = System.getProperty("test.src", "."); + private final static String DATA_DIR = + DIR + System.getProperty("file.separator") + "data"; + private final static String KEYSTORE_VERIFY = + DATA_DIR + System.getProperty("file.separator") + "certs" + + System.getProperty("file.separator") + "xmldsig.jks"; + private final static String KEYSTORE_SIGN = + DATA_DIR + System.getProperty("file.separator") + "certs" + + System.getProperty("file.separator") + "test.jks"; + private final static String STYLESHEET = + "http://www.w3.org/TR/xml-stylesheet"; + private final static String STYLESHEET_B64 = + "http://www.w3.org/Signature/2002/04/xml-stylesheet.b64"; + private final static char[] PASS = "changeit".toCharArray(); + + public static void main(String args[]) throws Throwable { + if (!args[0].equals("default")) { + Security.setProperty("jdk.xml.dsig.hereFunctionSupported", args[0]); + } + // Re-enable sha1 algs + SecurityUtils.removeAlgsFromDSigPolicy("sha1"); + + boolean expected = Boolean.parseBoolean(args[1]); + + sign(expected); + + // Validating an old signature signed by JDK < 21 + validate(expected); + } + + static void validate(boolean expected) throws Exception { + SignatureValidator validator = new SignatureValidator(new File(DATA_DIR)); + + KeyStore keystore = KeyStore.getInstance(new File(KEYSTORE_VERIFY), PASS); + KeySelector ks = new X509KeySelector(keystore, false); + + if (expected) { + Asserts.assertTrue(validator.validate( + "signature.xml", ks, new HttpURIDereferencer(), false)); + } else { + Utils.runAndCheckException(() -> validator.validate( + "signature.xml", ks, new HttpURIDereferencer(), false), + XMLSignatureException.class); + } + } + + static void sign(boolean expected) throws Exception { + XMLSignatureFactory fac = XMLSignatureFactory.getInstance(); + DigestMethod sha1 = fac.newDigestMethod(DigestMethod.SHA1, null); + CanonicalizationMethod withoutComments = fac.newCanonicalizationMethod + (CanonicalizationMethod.INCLUSIVE, (C14NMethodParameterSpec)null); + SignatureMethod dsaSha1 = fac.newSignatureMethod(SignatureMethod.DSA_SHA1, null); + KeyInfoFactory kifac = fac.getKeyInfoFactory(); + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + dbf.setNamespaceAware(true); + + String ENVELOPE = + DATA_DIR + System.getProperty("file.separator") + "envelope.xml"; + + var ks = KeyStore.getInstance(new File(KEYSTORE_SIGN), PASS); + var signingKey = ks.getKey("user", PASS); + var signingCert = ks.getCertificate("user"); + + // create references + List refs = new ArrayList<>(); + + // Reference 1 + refs.add(fac.newReference(STYLESHEET, sha1)); + + // Reference 2 + String expr = "\n" + + " ancestor-or-self::dsig:SignedInfo " + "\n" + + " and " + "\n" + + " count(ancestor-or-self::dsig:Reference | " + "\n" + + " here()/ancestor::dsig:Reference[1]) > " + "\n" + + " count(ancestor-or-self::dsig:Reference) " + "\n" + + " or " + "\n" + + " count(ancestor-or-self::node() | " + "\n" + + " id('notaries')) = " + "\n" + + " count(ancestor-or-self::node()) " + "\n"; + + XPathFilterParameterSpec xfp = new XPathFilterParameterSpec(expr, + Collections.singletonMap("dsig", XMLSignature.XMLNS)); + refs.add(fac.newReference("", sha1, Collections.singletonList + (fac.newTransform(Transform.XPATH, xfp)), + XMLObject.TYPE, null)); + + // create SignedInfo + SignedInfo si = fac.newSignedInfo(withoutComments, dsaSha1, refs); + + // create keyinfo + KeyInfo ki = kifac.newKeyInfo(List.of( + kifac.newX509Data(List.of(signingCert))), null); + + // create XMLSignature + XMLSignature sig = fac.newXMLSignature(si, ki, null, "signature", null); + + dbf.setValidating(false); + Document envDoc = dbf.newDocumentBuilder() + .parse(new FileInputStream(ENVELOPE)); + Element ys = (Element) + envDoc.getElementsByTagName("YoursSincerely").item(0); + + DOMSignContext dsc = new DOMSignContext(signingKey, ys); + dsc.setURIDereferencer(new HttpURIDereferencer()); + + if (expected) { + sig.sign(dsc); + } else { + Utils.runAndCheckException( + () -> sig.sign(dsc), XMLSignatureException.class); + return; // Signing fails, no need to validate + } + +// StringWriter sw = new StringWriter(); +// dumpDocument(envDoc, sw); + + NodeList nl = + envDoc.getElementsByTagNameNS(XMLSignature.XMLNS, "Signature"); + if (nl.getLength() == 0) { + throw new Exception("Couldn't find signature Element"); + } + Element sigElement = (Element) nl.item(0); + + DOMValidateContext dvc = new DOMValidateContext + (new X509KeySelector(ks), sigElement); + dvc.setURIDereferencer(new HttpURIDereferencer()); + File f = new File( + System.getProperty("dir.test.vector.baltimore") + + System.getProperty("file.separator") + + "merlin-xmldsig-twenty-three" + + System.getProperty("file.separator")); + dvc.setBaseURI(f.toURI().toString()); + + XMLSignature sig2 = fac.unmarshalXMLSignature(dvc); + + if (sig.equals(sig2) == false) { + throw new Exception + ("Unmarshalled signature is not equal to generated signature"); + } + if (sig2.validate(dvc) == false) { + throw new Exception("Validation of generated signature failed"); + } + } + + /** + * This URIDereferencer returns locally cached copies of http content to + * avoid test failures due to network glitches, etc. + */ + private static class HttpURIDereferencer implements URIDereferencer { + private final URIDereferencer defaultUd; + + HttpURIDereferencer() { + defaultUd = XMLSignatureFactory.getInstance().getURIDereferencer(); + } + + public Data dereference(final URIReference ref, XMLCryptoContext ctx) + throws URIReferenceException { + String uri = ref.getURI(); + if (uri.equals(STYLESHEET) || uri.equals(STYLESHEET_B64)) { + try { + FileInputStream fis = new FileInputStream(new File + (DATA_DIR, uri.substring(uri.lastIndexOf('/')))); + return new OctetStreamData(fis,ref.getURI(),ref.getType()); + } catch (Exception e) { throw new URIReferenceException(e); } + } + + // fallback on builtin deref + return defaultUd.dereference(ref, ctx); + } + } +} diff --git a/test/jdk/javax/xml/crypto/dsig/SecureValidation.java b/test/jdk/javax/xml/crypto/dsig/SecureValidation.java index 2e6669a9672..04291f8264b 100644 --- a/test/jdk/javax/xml/crypto/dsig/SecureValidation.java +++ b/test/jdk/javax/xml/crypto/dsig/SecureValidation.java @@ -29,6 +29,7 @@ * @library /test/lib * @modules java.base/sun.security.tools.keytool * java.base/sun.security.x509 + * @run main/othervm SecureValidation */ import jdk.test.lib.Asserts; import jdk.test.lib.security.XMLUtils; diff --git a/test/lib/jdk/test/lib/security/XMLUtils.java b/test/lib/jdk/test/lib/security/XMLUtils.java index fa93e3f6b00..6e6495789d6 100644 --- a/test/lib/jdk/test/lib/security/XMLUtils.java +++ b/test/lib/jdk/test/lib/security/XMLUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,7 +23,6 @@ package jdk.test.lib.security; -import jdk.test.lib.Asserts; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -49,15 +48,14 @@ import javax.xml.transform.stream.StreamResult; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; -import java.io.File; import java.io.StringReader; import java.io.StringWriter; import java.net.URI; -import java.nio.file.Files; -import java.nio.file.Path; import java.security.*; import java.security.cert.X509Certificate; +import java.security.interfaces.EdECPrivateKey; import java.security.interfaces.RSAKey; +import java.security.spec.NamedParameterSpec; import java.security.spec.PSSParameterSpec; import java.util.*; @@ -68,37 +66,6 @@ public class XMLUtils { private static final XMLSignatureFactory FAC = XMLSignatureFactory.getInstance("DOM"); - //////////// MAIN as TEST //////////// - public static void main(String[] args) throws Exception { - var x = "cx"; - var p = Files.write(Path.of("x.xml"), List.of(x)); - var b = Path.of("").toUri().toString(); - var d = string2doc(x); - // keytool -keystore ks -keyalg ec -storepass changeit -genkeypair -alias a -dname CN=a - var pass = "changeit".toCharArray(); - var ks = KeyStore.getInstance(new File("ks"), pass); - var c = (X509Certificate) ks.getCertificate("a"); - var pr = (PrivateKey) ks.getKey("a", pass); - var pu = c.getPublicKey(); - var s0 = signer(pr); // No KeyInfo - var s1 = signer(pr, pu); // KeyInfo is PublicKey - var s2 = signer(pr, c); // KeyInfo is X509Data - var s3 = signer(ks, "a", pass); // KeyInfo is KeyName - var v1 = validator(); // knows nothing - var v2 = validator(ks); // knows KeyName - Asserts.assertTrue(v1.validate(s0.sign(d), pu)); // need PublicKey - Asserts.assertTrue(v1.validate(s1.sign(d))); // can read KeyInfo - Asserts.assertTrue(v1.validate(s2.sign(d))); // can read KeyInfo - Asserts.assertTrue(v2.validate(s3.sign(d))); // can read KeyInfo - Asserts.assertTrue(v2.secureValidation(false).validate(s3.sign(p.toUri()))); // can read KeyInfo - Asserts.assertTrue(v2.secureValidation(false).baseURI(b).validate( - s3.sign(p.toAbsolutePath().getParent().toUri(), p.getFileName().toUri()))); // can read KeyInfo - Asserts.assertTrue(v1.validate(s1.sign("text"))); // plain text - Asserts.assertTrue(v1.validate(s1.sign("binary".getBytes()))); // raw data - Asserts.assertTrue(v1.validate(s1.signEnveloping(d, "x", "#x"))); - Asserts.assertTrue(v1.validate(s1.signEnveloping(d, "x", "#xpointer(id('x'))"))); - } - //////////// CONVERT //////////// // Converts a Document object to string @@ -220,38 +187,20 @@ public class XMLUtils { public static class Signer { - PrivateKey privateKey; // signer key, never null + final PrivateKey privateKey; // signer key, never null + X509Certificate cert; // certificate, optional PublicKey publicKey; // public key, optional String keyName; // alias, optional - SignatureMethod sm; // default determined by privateKey - DigestMethod dm; // default SHA-256 - CanonicalizationMethod cm; // default EXCLUSIVE - Transform tr; // default ENVELOPED + String sm = null; // default determined by privateKey + SignatureMethodParameterSpec smSpec = null; + String dm = DigestMethod.SHA256; + String cm = CanonicalizationMethod.EXCLUSIVE; + String tr = Transform.ENVELOPED; - public Signer(PrivateKey privateKey) throws Exception { - this.privateKey = privateKey; - dm(DigestMethod.SHA256); - tr(Transform.ENVELOPED); - cm(CanonicalizationMethod.EXCLUSIVE); - String alg = privateKey.getAlgorithm(); - if (alg.equals("RSASSA-PSS")) { - PSSParameterSpec pspec - = (PSSParameterSpec) ((RSAKey) privateKey).getParams(); - if (pspec != null) { - sm(SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(pspec)); - } else { - sm(SignatureMethod.RSA_PSS); - } - } else { - sm(switch (privateKey.getAlgorithm()) { - case "RSA" -> SignatureMethod.RSA_SHA256; - case "DSA" -> SignatureMethod.DSA_SHA256; - case "EC" -> SignatureMethod.ECDSA_SHA256; - default -> throw new InvalidKeyException(); - }); - } + public Signer(PrivateKey privateKey) { + this.privateKey = Objects.requireNonNull(privateKey); } // Change KeyInfo source @@ -273,47 +222,29 @@ public class XMLUtils { // Change various methods - public Signer tr(String transform) throws Exception { - TransformParameterSpec params = null; - switch (transform) { - case Transform.XPATH: - params = new XPathFilterParameterSpec("//."); - break; - case Transform.XPATH2: - params = new XPathFilter2ParameterSpec( - Collections.singletonList(new XPathType("//.", - XPathType.Filter.INTERSECT))); - break; - } - tr = FAC.newTransform(transform, params); + public Signer tr(String transform) { + tr = Objects.requireNonNull(transform); + return this; + } + + public Signer dm(String method) { + dm = Objects.requireNonNull(method); + return this; + } + + public Signer cm(String method) { + cm = Objects.requireNonNull(method); + return this; + } + + public Signer sm(String method, SignatureMethodParameterSpec spec) { + sm = method; + smSpec = spec; return this; } public Signer sm(String method) throws Exception { - sm = FAC.newSignatureMethod(method, null); - return this; - } - - public Signer dm(String method) throws Exception { - dm = FAC.newDigestMethod(method, null); - return this; - } - - public Signer cm(String method) throws Exception { - cm = FAC.newCanonicalizationMethod(method, (C14NMethodParameterSpec) null); - return this; - } - - public Signer sm(String method, SignatureMethodParameterSpec spec) - throws Exception { - sm = FAC.newSignatureMethod(method, spec); - return this; - } - - public Signer dm(String method, DigestMethodParameterSpec spec) - throws Exception { - dm = FAC.newDigestMethod(method, spec); - return this; + return sm(method, null); } // Signs different sources @@ -353,7 +284,7 @@ public class XMLUtils { Document newDocument = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); FAC.newXMLSignature( - buildSignedInfo(FAC.newReference(ref, dm)), + buildSignedInfo(FAC.newReference(ref, FAC.newDigestMethod(dm, null))), buildKeyInfo(), List.of(FAC.newXMLObject(List.of(new DOMStructure(document.getDocumentElement())), id, null, null)), @@ -368,7 +299,7 @@ public class XMLUtils { Document newDocument = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); FAC.newXMLSignature( - buildSignedInfo(FAC.newReference("#object", dm, List.of + buildSignedInfo(FAC.newReference("#object", FAC.newDigestMethod(dm, null), List.of (FAC.newTransform(Transform.BASE64, (TransformParameterSpec) null)), null, null)), buildKeyInfo(), @@ -386,9 +317,11 @@ public class XMLUtils { Document newDocument = DocumentBuilderFactory.newInstance() .newDocumentBuilder().newDocument(); FAC.newXMLSignature( - buildSignedInfo(FAC.newReference("#object", dm)), + buildSignedInfo( + FAC.newReference("#object", FAC.newDigestMethod(dm, null))), buildKeyInfo(), - List.of(FAC.newXMLObject(List.of(new DOMStructure(newDocument.createTextNode(str))), + List.of(FAC.newXMLObject( + List.of(new DOMStructure(newDocument.createTextNode(str))), "object", null, null)), null, null) @@ -397,22 +330,61 @@ public class XMLUtils { } // Builds a SignedInfo for a string reference - private SignedInfo buildSignedInfo(String ref) { - return FAC.newSignedInfo( - cm, - sm, - List.of(FAC.newReference( + private SignedInfo buildSignedInfo(String ref) throws Exception { + return buildSignedInfo(FAC.newReference( ref, - dm, - List.of(tr), - null, null))); + FAC.newDigestMethod(dm, null), + List.of(FAC.newTransform(tr, switch (tr) { + case Transform.XPATH -> + new XPathFilterParameterSpec("//."); + case Transform.XPATH2 -> new XPathFilter2ParameterSpec( + Collections.singletonList(new XPathType("//.", + XPathType.Filter.INTERSECT))); + default -> null; + })), + null, null)); } // Builds a SignedInfo for a Reference - private SignedInfo buildSignedInfo(Reference ref) { + private SignedInfo buildSignedInfo(Reference ref) throws Exception { + SignatureMethod signatureMethod; + if (sm == null) { + String alg = privateKey.getAlgorithm().toUpperCase(Locale.ROOT); + if (alg.equals("RSASSA-PSS")) { + PSSParameterSpec pspec + = (PSSParameterSpec) ((RSAKey) privateKey).getParams(); + if (pspec != null) { + signatureMethod = FAC.newSignatureMethod( + SignatureMethod.RSA_PSS, new RSAPSSParameterSpec(pspec)); + } else { + signatureMethod = FAC.newSignatureMethod(SignatureMethod.RSA_PSS, null); + } + } else { + signatureMethod = FAC.newSignatureMethod(switch (alg) { + case "RSA" -> SignatureMethod.RSA_SHA256; + case "DSA" -> SignatureMethod.DSA_SHA256; + case "EC" -> SignatureMethod.ECDSA_SHA256; + case "ED25519" -> SignatureMethod.ED25519; + case "ED448" -> SignatureMethod.ED448; + case "EDDSA" -> { + if (privateKey instanceof EdECPrivateKey edsk) { + yield edsk.getParams().getName() + .equals(NamedParameterSpec.ED25519.getName()) + ? SignatureMethod.ED25519 + : SignatureMethod.ED448; + } else { + throw new InvalidKeyException(); + } + } + default -> throw new InvalidKeyException(); + }, null); + } + } else { + signatureMethod = FAC.newSignatureMethod(sm, smSpec); + } return FAC.newSignedInfo( - cm, - sm, + FAC.newCanonicalizationMethod(cm, (C14NMethodParameterSpec) null), + signatureMethod, List.of(ref)); } @@ -518,7 +490,9 @@ public class XMLUtils { AlgorithmMethod method, XMLCryptoContext context) throws KeySelectorException { - Objects.requireNonNull(keyInfo, "Null KeyInfo object!"); + if (keyInfo == null) { + throw new IllegalArgumentException("Null KeyInfo object!"); + } for (XMLStructure xmlStructure : keyInfo.getContent()) { PublicKey pk;