SANTUARIO-510 - Support RSASSA-PSS with Parameters - part II StAX. Thanks to Kunnar Klauks for the patch.
git-svn-id: https://svn.apache.org/repos/asf/santuario/xml-security-java/trunk@1874560 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/pom.xml b/pom.xml
index e627428..e2e1522 100644
--- a/pom.xml
+++ b/pom.xml
@@ -222,7 +222,7 @@
</instructions>
</configuration>
</plugin>
-
+
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
@@ -245,6 +245,7 @@
<schemaInclude>bindings/schemas/xmldsig11-schema.xsd</schemaInclude>
<schemaInclude>bindings/schemas/xenc-schema.xsd</schemaInclude>
<schemaInclude>bindings/schemas/xenc-schema-11.xsd</schemaInclude>
+ <schemaInclude>bindings/schemas/rsa-pss.xsd</schemaInclude>
</schemaIncludes>
<bindingDirectory>${basedir}/src/main/resources/bindings/</bindingDirectory>
<bindingIncludes>
@@ -255,6 +256,7 @@
<bindingInclude>xenc11.xjb</bindingInclude>
<bindingInclude>security-config.xjb</bindingInclude>
<bindingInclude>xop.xjb</bindingInclude>
+ <bindingInclude>rsa-pss.xjb</bindingInclude>
</bindingIncludes>
<catalog>${basedir}/src/main/resources/bindings/bindings.cat</catalog>
<forceRegenerate>false</forceRegenerate>
diff --git a/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureBaseRSA.java b/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureBaseRSA.java
index 51dfd73..2289d86 100644
--- a/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureBaseRSA.java
+++ b/src/main/java/org/apache/xml/security/algorithms/implementations/SignatureBaseRSA.java
@@ -692,7 +692,7 @@
rsaPssParamsElement.setAttributeNS(Constants.NamespaceSpecNS, "xmlns:" + "pss", Constants.XML_DSIG_NS_MORE_07_05);
Element digestMethodElement = XMLUtils.createElementInSignatureSpace(rsaPssParamsElement.getOwnerDocument(), Constants._TAG_DIGESTMETHOD);
- digestMethodElement.setAttribute(Constants._ATT_ALGORITHM, DigestAlgorithm.fromDigestAlgorithm(pssParameterSpec.getDigestAlgorithm()).getXmlDigestAlgorithm());
+ digestMethodElement.setAttributeNS(null, Constants._ATT_ALGORITHM, DigestAlgorithm.fromDigestAlgorithm(pssParameterSpec.getDigestAlgorithm()).getXmlDigestAlgorithm());
XMLUtils.addReturnToElement(rsaPssParamsElement);
rsaPssParamsElement.appendChild(digestMethodElement);
XMLUtils.addReturnToElement(rsaPssParamsElement);
diff --git a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java
index 13cc5ed..0ae7f18 100644
--- a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java
+++ b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityConstants.java
@@ -124,6 +124,7 @@
public static final String NS_XMLENC11 = "http://www.w3.org/2009/xmlenc11#";
public static final String NS_DSIG = "http://www.w3.org/2000/09/xmldsig#";
public static final String NS_DSIG_MORE ="http://www.w3.org/2001/04/xmldsig-more#";
+ public static final String NS_DSIG_MORE_2007_05 = "http://www.w3.org/2007/05/xmldsig-more#";
public static final String NS_DSIG11 = "http://www.w3.org/2009/xmldsig11#";
public static final String NS_WSSE11 = "http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd";
public static final String NS_XOP = "http://www.w3.org/2004/08/xop/include";
@@ -144,6 +145,7 @@
public static final QName TAG_xenc11_MGF = new QName(NS_XMLENC11, "MGF", PREFIX_XENC11);
public static final String PREFIX_DSIG = "dsig";
+ public static final String PREFIX_DSIG_MORE_PSS = "pss";
public static final QName TAG_dsig_KeyInfo = new QName(NS_DSIG, "KeyInfo", PREFIX_DSIG);
public static final QName TAG_xenc_EncryptionProperties = new QName(NS_XMLENC, "EncryptionProperties", PREFIX_XENC);
@@ -261,6 +263,10 @@
public static final Action SIGNATURE = new Action("Signature");
public static final Action ENCRYPT = new Action("Encrypt");
+ public static final QName TAG_dsigmore_RSAPSSPARAMS = new QName(NS_DSIG_MORE_2007_05, "RSAPSSParams", PREFIX_DSIG_MORE_PSS);
+ public static final QName TAG_dsigmore_SALTLENGTH = new QName(NS_DSIG_MORE_2007_05, "SaltLength", PREFIX_DSIG_MORE_PSS);
+ public static final QName TAG_dsigmore_TRAILERFIELD = new QName(NS_DSIG_MORE_2007_05, "TrailerField", PREFIX_DSIG_MORE_PSS);
+
public static class Action extends ComparableType<Action> {
public Action(String name) {
super(name);
diff --git a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java
index eec0e7f..8ee89f4 100644
--- a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java
+++ b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityProperties.java
@@ -22,6 +22,7 @@
import java.security.Key;
import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
import java.util.*;
import javax.xml.namespace.QName;
@@ -78,6 +79,7 @@
private QName signaturePositionQName;
private boolean signaturePositionStart = false;
+ private AlgorithmParameterSpec algorithmParameterSpec;
public XMLSecurityProperties() {
}
@@ -117,6 +119,7 @@
this.signatureIncludeDigestTransform = xmlSecurityProperties.signatureIncludeDigestTransform;
this.signaturePositionQName = xmlSecurityProperties.signaturePositionQName;
this.signaturePositionStart = xmlSecurityProperties.signaturePositionStart;
+ this.algorithmParameterSpec = xmlSecurityProperties.algorithmParameterSpec;
}
public boolean isSignaturePositionStart() {
@@ -528,4 +531,12 @@
public void setSignaturePositionQName(QName signaturePositionQName) {
this.signaturePositionQName = signaturePositionQName;
}
+
+ public AlgorithmParameterSpec getAlgorithmParameterSpec() {
+ return algorithmParameterSpec;
+ }
+
+ public void setAlgorithmParameterSpec(AlgorithmParameterSpec algorithmParameterSpec) {
+ this.algorithmParameterSpec = algorithmParameterSpec;
+ }
}
diff --git a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java
index 8f7591e..0c58c9e 100644
--- a/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java
+++ b/src/main/java/org/apache/xml/security/stax/ext/XMLSecurityUtils.java
@@ -538,6 +538,11 @@
concreteLSInput.setByteStream(
ClassLoaderUtils.getResourceAsStream("bindings/schemas/xml.xsd", XMLSecurityConstants.class));
return concreteLSInput;
+ } else if ("rsa-pss.xsd".equals(systemId)) {
+ ConcreteLSInput concreteLSInput = new ConcreteLSInput();
+ concreteLSInput.setByteStream(
+ ClassLoaderUtils.getResourceAsStream("bindings/schemas/rsa-pss.xsd", XMLSecurityConstants.class));
+ return concreteLSInput;
}
return null;
}
@@ -550,6 +555,7 @@
new StreamSource(ClassLoaderUtils.getResourceAsStream("bindings/schemas/xenc-schema.xsd", XMLSecurityConstants.class)),
new StreamSource(ClassLoaderUtils.getResourceAsStream("bindings/schemas/xenc-schema-11.xsd", XMLSecurityConstants.class)),
new StreamSource(ClassLoaderUtils.getResourceAsStream("bindings/schemas/xmldsig11-schema.xsd", XMLSecurityConstants.class)),
+ new StreamSource(ClassLoaderUtils.getResourceAsStream("bindings/schemas/rsa-pss.xsd", XMLSecurityConstants.class))
}
);
return schema;
diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureInputHandler.java b/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureInputHandler.java
index a679ed3..3807af0 100644
--- a/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureInputHandler.java
+++ b/src/main/java/org/apache/xml/security/stax/impl/processor/input/AbstractSignatureInputHandler.java
@@ -18,11 +18,15 @@
*/
package org.apache.xml.security.stax.impl.processor.input;
+import org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.SignatureRSASSAPSS.DigestAlgorithm;
import org.apache.xml.security.binding.excc14n.InclusiveNamespaces;
import org.apache.xml.security.binding.xmldsig.CanonicalizationMethodType;
+import org.apache.xml.security.binding.xmldsig.SignatureMethodType;
import org.apache.xml.security.binding.xmldsig.SignatureType;
import org.apache.xml.security.binding.xmldsig.SignedInfoType;
+import org.apache.xml.security.binding.xmldsig.pss.RSAPSSParams;
import org.apache.xml.security.exceptions.XMLSecurityException;
+import org.apache.xml.security.signature.XMLSignature;
import org.apache.xml.security.stax.impl.transformer.canonicalizer.Canonicalizer20010315_Excl;
import org.apache.xml.security.stax.impl.util.IDGenerator;
import org.apache.xml.security.stax.impl.util.SignerOutputStream;
@@ -57,7 +61,16 @@
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
-import java.util.*;
+import java.security.spec.MGF1ParameterSpec;
+import java.security.spec.PSSParameterSpec;
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import static org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.SignatureRSASSAPSS.DigestAlgorithm.SHA256;
+import static org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.SignatureRSASSAPSS.DigestAlgorithm.fromXmlDigestAlgorithm;
/**
*/
@@ -306,6 +319,10 @@
SignatureAlgorithm signatureAlgorithm =
SignatureAlgorithmFactory.getInstance().getSignatureAlgorithm(
algorithmURI);
+ if (XMLSignature.ALGO_ID_SIGNATURE_RSA_PSS.equals(algorithmURI)) {
+ PSSParameterSpec spec = rsaPSSParameterSpec(signatureType);
+ signatureAlgorithm.engineSetParameter(spec);
+ }
signatureAlgorithm.engineInitVerify(verifyKey);
signerOutputStream = new SignerOutputStream(signatureAlgorithm);
bufferedSignerOutputStream = new UnsyncBufferedOutputStream(signerOutputStream);
@@ -347,6 +364,31 @@
}
}
+ private PSSParameterSpec rsaPSSParameterSpec(SignatureType signatureType) throws XMLSecurityException {
+ SignatureMethodType signatureMethod = signatureType.getSignedInfo().getSignatureMethod();
+ RSAPSSParams rsapssParams = null;
+ for (Object o : signatureMethod.getContent()) {
+ if (o instanceof RSAPSSParams) {
+ rsapssParams = (RSAPSSParams) o;
+ break;
+ }
+ }
+ if (rsapssParams == null) {
+ throw new XMLSecurityException("algorithms.MissingRSAPSSParams");
+ }
+
+ String digestMethod = rsapssParams.getDigestMethod() == null ? SHA256.getXmlDigestAlgorithm() : rsapssParams.getDigestMethod().getAlgorithm();
+ String maskGenerationDigestMethod = rsapssParams.getMaskGenerationFunction() == null ? SHA256.getXmlDigestAlgorithm() : rsapssParams.getMaskGenerationFunction().getDigestMethod().getAlgorithm();
+ DigestAlgorithm digestAlgorithm = fromXmlDigestAlgorithm(digestMethod);
+
+ int saltLength = rsapssParams.getSaltLength() == null ? digestAlgorithm.getSaltLength() : rsapssParams.getSaltLength();
+ int trailerField = rsapssParams.getTrailerField() == null ? 1 : rsapssParams.getTrailerField();
+ String maskDigestAlgorithm = fromXmlDigestAlgorithm(maskGenerationDigestMethod).getDigestAlgorithm();
+
+ return new PSSParameterSpec(digestAlgorithm.getDigestAlgorithm(), "MGF1",
+ new MGF1ParameterSpec(maskDigestAlgorithm), saltLength, trailerField);
+ }
+
protected void processEvent(XMLSecEvent xmlSecEvent) throws XMLStreamException {
transformer.transform(xmlSecEvent);
}
diff --git a/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java b/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java
index 7a1f091..0607f45 100644
--- a/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java
+++ b/src/main/java/org/apache/xml/security/stax/impl/processor/output/AbstractSignatureEndingOutputProcessor.java
@@ -23,6 +23,7 @@
import java.security.Key;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
+import java.security.spec.PSSParameterSpec;
import java.util.*;
import javax.security.auth.DestroyFailedException;
@@ -53,6 +54,8 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import static org.apache.xml.security.algorithms.implementations.SignatureBaseRSA.SignatureRSASSAPSS.DigestAlgorithm.fromDigestAlgorithm;
+
/**
*/
public abstract class AbstractSignatureEndingOutputProcessor extends AbstractBufferingOutputProcessor {
@@ -124,6 +127,9 @@
try {
signatureAlgorithm = SignatureAlgorithmFactory.getInstance().getSignatureAlgorithm(
getSecurityProperties().getSignatureAlgorithm());
+ if (getSecurityProperties().getAlgorithmParameterSpec() != null) {
+ signatureAlgorithm.engineSetParameter(getSecurityProperties().getAlgorithmParameterSpec());
+ }
} catch (NoSuchAlgorithmException e) {
throw new XMLSecurityException(e);
} catch (NoSuchProviderException e) {
@@ -173,6 +179,27 @@
attributes = new ArrayList<>(1);
attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, getSecurityProperties().getSignatureAlgorithm()));
createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_SignatureMethod, false, attributes);
+
+ if (getSecurityProperties().getAlgorithmParameterSpec() instanceof PSSParameterSpec) {
+ PSSParameterSpec pssParams = (PSSParameterSpec) getSecurityProperties().getAlgorithmParameterSpec();
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsigmore_RSAPSSPARAMS, false, null);
+
+ attributes = new ArrayList<>(1);
+ attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, fromDigestAlgorithm(pssParams.getDigestAlgorithm()).getXmlDigestAlgorithm()));
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_DigestMethod, false, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_DigestMethod);
+
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsigmore_SALTLENGTH, false, null);
+ createCharactersAndOutputAsEvent(subOutputProcessorChain, String.valueOf(pssParams.getSaltLength()));
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsigmore_SALTLENGTH);
+
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsigmore_TRAILERFIELD, false, null);
+ createCharactersAndOutputAsEvent(subOutputProcessorChain, String.valueOf(pssParams.getTrailerField()));
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsigmore_TRAILERFIELD);
+
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsigmore_RSAPSSPARAMS);
+ }
+
createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_SignatureMethod);
Iterator<SignaturePartDef> signaturePartDefIterator = signaturePartDefList.iterator();
diff --git a/src/main/resources/bindings/rsa-pss.xjb b/src/main/resources/bindings/rsa-pss.xjb
new file mode 100644
index 0000000..57a442a
--- /dev/null
+++ b/src/main/resources/bindings/rsa-pss.xjb
@@ -0,0 +1,10 @@
+<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
+ xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ version="2.1">
+ <bindings schemaLocation="schemas/rsa-pss.xsd" version="1.0">
+ <schemaBindings>
+ <package name="org.apache.xml.security.binding.xmldsig.pss"/>
+ </schemaBindings>
+ </bindings>
+</bindings>
diff --git a/src/main/resources/bindings/schemas/rsa-pss.xsd b/src/main/resources/bindings/schemas/rsa-pss.xsd
new file mode 100644
index 0000000..17d4486
--- /dev/null
+++ b/src/main/resources/bindings/schemas/rsa-pss.xsd
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Schema for XML Signatures (more types)
+http://www.w3.org/2000/09/xmldsig-more#
+Refer to RFC 6931 2.3.9 [1].
+[1] https://tools.ietf.org/html/rfc6931
+-->
+
+<schema xmlns="http://www.w3.org/2001/XMLSchema"
+ xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
+ xmlns:dsm="http://www.w3.org/2007/05/xmldsig-more#"
+ targetNamespace="http://www.w3.org/2007/05/xmldsig-more#"
+ version="0.1" elementFormDefault="qualified">
+
+ <import namespace="http://www.w3.org/2000/09/xmldsig#"
+ schemaLocation="xmldsig-core-schema.xsd" />
+
+ <element name="RSAPSSParams">
+ <annotation>
+ <documentation>
+ Top level element that can be used in xs:any namespace="#other"
+ wildcard of ds:SignatureMethod content.
+ </documentation>
+ </annotation>
+ <complexType>
+ <complexContent>
+ <extension base="dsm:RSAPSSParamsType">
+ <sequence />
+ </extension>
+ </complexContent>
+ </complexType>
+ </element>
+ <complexType name="RSAPSSParamsType">
+ <sequence>
+ <element ref="ds:DigestMethod" minOccurs="0"/>
+ <element name="MaskGenerationFunction"
+ type="dsm:MaskGenerationFunctionType" minOccurs="0"/>
+ <element name="SaltLength" type="int"
+ minOccurs="0"/>
+ <element name="TrailerField" type="int"
+ minOccurs="0"/>
+ </sequence>
+ </complexType>
+
+ <complexType name="MaskGenerationFunctionType">
+ <sequence>
+ <element ref="ds:DigestMethod" minOccurs="0"/>
+ </sequence>
+ <attribute name="Algorithm" type="anyURI"
+ default="http://www.w3.org/2007/05/xmldsig-more#MGF1"/>
+ </complexType>
+
+</schema>
diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureVerificationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureVerificationTest.java
index 3d91266..c884ecb 100644
--- a/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureVerificationTest.java
+++ b/src/test/java/org/apache/xml/security/test/stax/signature/AbstractSignatureVerificationTest.java
@@ -21,6 +21,7 @@
import java.io.File;
import java.security.Key;
import java.security.cert.X509Certificate;
+import java.security.spec.AlgorithmParameterSpec;
import java.util.List;
import java.util.UUID;
@@ -158,7 +159,7 @@
String c14nMethod
) throws Exception {
String digestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
- return signUsingDOM(algorithm, document, localNames, signingKey, c14nMethod, digestMethod, null, c14nMethod, null);
+ return signUsingDOM(algorithm, document, localNames, signingKey, c14nMethod, digestMethod, null, null, null);
}
/**
@@ -175,7 +176,7 @@
) throws Exception {
String digestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
return signUsingDOM(algorithm, document, localNames, signingKey,
- c14nMethod, digestMethod, additionalReferences, c14nMethod, resourceResolverSpi);
+ c14nMethod, digestMethod, additionalReferences, resourceResolverSpi, null);
}
/**
@@ -191,7 +192,7 @@
) throws Exception {
String digestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
return signUsingDOM(algorithm, document, localNames, signingKey,
- c14nMethod, digestMethod, additionalReferences, c14nMethod, null);
+ c14nMethod, digestMethod, additionalReferences, null, null);
}
/**
@@ -205,7 +206,7 @@
String c14nMethod,
String digestMethod
) throws Exception {
- return signUsingDOM(algorithm, document, localNames, signingKey, c14nMethod, digestMethod, null, c14nMethod, null);
+ return signUsingDOM(algorithm, document, localNames, signingKey, c14nMethod, digestMethod, null, null, null);
}
/**
@@ -219,10 +220,10 @@
String c14nMethod,
String digestMethod,
List<ReferenceInfo> additionalReferences,
- String referenceC14NMethod,
- ResourceResolverSpi resourceResolverSpi
+ ResourceResolverSpi resourceResolverSpi,
+ AlgorithmParameterSpec spec
) throws Exception {
- XMLSignature sig = new XMLSignature(document, "", algorithm, c14nMethod);
+ XMLSignature sig = new XMLSignature(document, "", algorithm, 0, c14nMethod, null, spec);
if (resourceResolverSpi != null) {
sig.addResourceResolver(resourceResolverSpi);
}
@@ -245,7 +246,7 @@
elementToSign.setIdAttributeNS(null, "Id", true);
Transforms transforms = new Transforms(document);
- transforms.addTransform(referenceC14NMethod);
+ transforms.addTransform(c14nMethod);
sig.addDocument("#" + id, transforms, digestMethod);
}
}
diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java
index d72e8cf..bdd8591 100644
--- a/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java
+++ b/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureCreationTest.java
@@ -27,6 +27,7 @@
import java.security.KeyPairGenerator;
import java.security.Provider;
import java.security.Security;
+import java.security.spec.PSSParameterSpec;
import java.util.ArrayList;
import java.util.List;
@@ -40,6 +41,7 @@
import org.apache.xml.security.stax.ext.XMLSecurityConstants;
import org.apache.xml.security.stax.ext.XMLSecurityProperties;
import org.apache.xml.security.stax.securityToken.SecurityTokenConstants;
+import org.apache.xml.security.test.dom.TestUtils;
import org.apache.xml.security.test.stax.utils.XmlReaderToWriter;
import org.apache.xml.security.utils.XMLUtils;
import org.junit.jupiter.api.Assumptions;
@@ -47,6 +49,8 @@
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
+import static java.security.spec.MGF1ParameterSpec.SHA256;
+
/**
* A set of test-cases for Signature creation with various PublicKey algorithms
*/
@@ -531,6 +535,52 @@
}
@Test
+ public void testRSA_SSA_PSS() throws Exception {
+ Assumptions.assumeTrue(bcInstalled || TestUtils.isJava11Compatible());
+
+ // Set up the Configuration
+ XMLSecurityProperties properties = new XMLSecurityProperties();
+ List<XMLSecurityConstants.Action> actions = new ArrayList<>();
+ actions.add(XMLSecurityConstants.SIGNATURE);
+ properties.setActions(actions);
+ properties.setSignatureKeyIdentifier(SecurityTokenConstants.KeyIdentifier_KeyValue);
+
+ String signatureAlgorithm = "http://www.w3.org/2007/05/xmldsig-more#rsa-pss";
+ properties.setAlgorithmParameterSpec(new PSSParameterSpec("SHA-256", "MGF1", SHA256, 32, 1));
+ properties.setSignatureAlgorithm(signatureAlgorithm);
+ properties.setSignatureKey(rsaKeyPair.getPrivate());
+ properties.setSignatureVerificationKey(rsaKeyPair.getPublic());
+
+ SecurePart securePart = new SecurePart(
+ new QName("urn:example:po", "PaymentInfo"),
+ SecurePart.Modifier.Content,
+ new String[]{"http://www.w3.org/2001/10/xml-exc-c14n#"},
+ "http://www.w3.org/2000/09/xmldsig#sha1");
+ properties.addSignaturePart(securePart);
+
+ OutboundXMLSec outboundXMLSec = XMLSec.getOutboundXMLSec(properties);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ XMLStreamWriter xmlStreamWriter = outboundXMLSec.processOutMessage(baos, "UTF-8");
+
+ InputStream sourceDocument =
+ this.getClass().getClassLoader().getResourceAsStream(
+ "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+ XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
+
+ XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+ xmlStreamWriter.close();
+
+ // System.out.println("Got:\n" + new String(baos.toByteArray(), StandardCharsets.UTF_8.name()));
+ Document document = null;
+ try (InputStream is = new ByteArrayInputStream(baos.toByteArray())) {
+ document = XMLUtils.read(is, false);
+ }
+
+ // Verify using DOM
+ verifyUsingDOM(document, rsaKeyPair.getPublic(), properties.getSignatureSecureParts());
+ }
+
+ @Test
public void testECDSA_SHA1() throws Exception {
// Set up the Configuration
XMLSecurityProperties properties = new XMLSecurityProperties();
diff --git a/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureVerificationTest.java b/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureVerificationTest.java
index c781959..75d2e5e 100644
--- a/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureVerificationTest.java
+++ b/src/test/java/org/apache/xml/security/test/stax/signature/PKSignatureVerificationTest.java
@@ -26,6 +26,7 @@
import java.security.KeyPairGenerator;
import java.security.Provider;
import java.security.Security;
+import java.security.spec.PSSParameterSpec;
import java.util.ArrayList;
import java.util.List;
@@ -44,9 +45,12 @@
import org.apache.xml.security.utils.XMLUtils;
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.w3c.dom.Document;
+import static java.security.spec.MGF1ParameterSpec.SHA256;
+
/**
* A set of test-cases for Signature verification with various PublicKey algorithms
*/
@@ -511,6 +515,53 @@
}
@Test
+ @Disabled // Disabled as I didn't want to have to change the XML Signature core schema
+ public void testRSA_SSA_PSS() throws Exception {
+ Assumptions.assumeTrue(bcInstalled);
+
+ // Read in plaintext document
+ InputStream sourceDocument =
+ this.getClass().getClassLoader().getResourceAsStream(
+ "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+ Document document = XMLUtils.read(sourceDocument, false);
+
+ String signatureAlgorithm = "http://www.w3.org/2007/05/xmldsig-more#rsa-pss";
+ List<String> localNames = new ArrayList<>();
+ localNames.add("PaymentInfo");
+
+ PSSParameterSpec spec = new PSSParameterSpec("SHA-256", "MGF1", SHA256, 64, 1);
+ String c14nMethod = "http://www.w3.org/2001/10/xml-exc-c14n#";
+ String digestMethod = "http://www.w3.org/2000/09/xmldsig#sha1";
+
+ signUsingDOM(
+ signatureAlgorithm, document, localNames, rsaKeyPair.getPrivate(),
+ c14nMethod, digestMethod, null, null, spec
+ );
+
+ XMLUtils.outputDOM(document, System.out);
+
+ // Convert Document to a Stream Reader
+ javax.xml.transform.Transformer transformer = transformerFactory.newTransformer();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ transformer.transform(new DOMSource(document), new StreamResult(baos));
+
+ XMLStreamReader xmlStreamReader = null;
+ try (InputStream is = new ByteArrayInputStream(baos.toByteArray())) {
+ xmlStreamReader = xmlInputFactory.createXMLStreamReader(is);
+ }
+
+ // Verify signature
+ XMLSecurityProperties properties = new XMLSecurityProperties();
+ properties.setSignatureVerificationKey(rsaKeyPair.getPublic());
+ InboundXMLSec inboundXMLSec = XMLSec.getInboundWSSec(properties);
+ TestSecurityEventListener securityEventListener = new TestSecurityEventListener();
+ XMLStreamReader securityStreamReader =
+ inboundXMLSec.processInMessage(xmlStreamReader, null, securityEventListener);
+
+ StAX2DOM.readDoc(securityStreamReader);
+ }
+
+ @Test
public void testECDSA_SHA1() throws Exception {
// Read in plaintext document
InputStream sourceDocument =