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 =