You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@santuario.apache.org by co...@apache.org on 2012/06/29 13:16:21 UTC
svn commit: r1355316 - in /santuario/xml-security-java/trunk/src:
main/java/org/apache/xml/security/stax/ext/
main/java/org/apache/xml/security/stax/impl/processor/output/
test/java/org/apache/xml/security/test/dom/
test/java/org/apache/xml/security/te...
Author: coheigea
Date: Fri Jun 29 11:16:19 2012
New Revision: 1355316
URL: http://svn.apache.org/viewvc?rev=1355316&view=rev
Log:
[SANTUARIO-316] - Added initial outbound processors for streaming Signature + a basic testcase
Added:
santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java
santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java
santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/
santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureTest.java
Modified:
santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java
santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/DSNamespaceContext.java
Modified: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java?rev=1355316&r1=1355315&r2=1355316&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java (original)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/ext/AbstractOutputProcessor.java Fri Jun 29 11:16:19 2012
@@ -126,7 +126,8 @@ public abstract class AbstractOutputProc
for (int i = 0; i < attributeList.size(); i++) {
XMLSecAttribute xmlSecAttribute = attributeList.get(i);
final QName attributeName = xmlSecAttribute.getName();
- if (attributeName.getNamespaceURI() != null && !declaredNamespaces.contains(xmlSecAttribute.getAttributeNamespace())) {
+ if (attributeName.getNamespaceURI() != null && !"".equals(attributeName.getNamespaceURI())
+ && !declaredNamespaces.contains(xmlSecAttribute.getAttributeNamespace())) {
declaredNamespaces.add(xmlSecAttribute.getAttributeNamespace());
}
}
Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java?rev=1355316&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureEndingOutputProcessor.java Fri Jun 29 11:16:19 2012
@@ -0,0 +1,178 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.xml.security.stax.impl.processor.output;
+
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Deque;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+
+import org.apache.xml.security.stax.ext.AbstractBufferingOutputProcessor;
+import org.apache.xml.security.stax.ext.OutputProcessorChain;
+import org.apache.xml.security.stax.ext.SecurityToken;
+import org.apache.xml.security.stax.ext.XMLSecurityConstants;
+import org.apache.xml.security.stax.ext.XMLSecurityException;
+import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
+import org.apache.xml.security.stax.ext.stax.XMLSecEndElement;
+import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
+import org.apache.xml.security.stax.impl.SignaturePartDef;
+import org.apache.xml.security.stax.impl.algorithms.SignatureAlgorithm;
+
+/**
+ * An EndingOutputProcessor for XML Signature.
+ */
+public class XMLSignatureEndingOutputProcessor extends AbstractSignatureEndingOutputProcessor {
+
+ private SignedInfoProcessor signedInfoProcessor = null;
+
+ public XMLSignatureEndingOutputProcessor(XMLSignatureOutputProcessor signatureOutputProcessor) throws XMLSecurityException {
+ super(signatureOutputProcessor);
+ this.addAfterProcessor(XMLSignatureOutputProcessor.class.getName());
+ }
+
+ @Override
+ public void doFinal(OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
+ setAppendAfterThisTokenId(outputProcessorChain.getSecurityContext().<String>get(XMLSecurityConstants.PROP_APPEND_SIGNATURE_ON_THIS_ID));
+ OutputProcessorChain subOutputProcessorChain = outputProcessorChain.createSubChain(this);
+ flushBufferAndCallbackAfterTokenID(subOutputProcessorChain, this, getXmlSecEventBuffer());
+ //call final on the rest of the chain
+ subOutputProcessorChain.doFinal();
+ //this processor is now finished and we can remove it now
+ subOutputProcessorChain.removeProcessor(this);
+ }
+
+ @Override
+ protected SignedInfoProcessor newSignedInfoProcessor(SignatureAlgorithm signatureAlgorithm, OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
+ this.signedInfoProcessor = new SignedInfoProcessor(signatureAlgorithm);
+ this.signedInfoProcessor.setXMLSecurityProperties(getSecurityProperties());
+ this.signedInfoProcessor.setAction(getAction());
+ this.signedInfoProcessor.addAfterProcessor(XMLSignatureEndingOutputProcessor.class.getName());
+ this.signedInfoProcessor.init(outputProcessorChain);
+ return this.signedInfoProcessor;
+ }
+
+ @Override
+ protected void createKeyInfoStructureForSignature(
+ OutputProcessorChain outputProcessorChain,
+ SecurityToken securityToken,
+ boolean useSingleCertificate)
+ throws XMLStreamException, XMLSecurityException {
+ // Issuer-Serial by default
+ X509Certificate[] x509Certificates = securityToken.getX509Certificates();
+ if (x509Certificates != null) {
+ createX509IssuerSerialStructure(outputProcessorChain, x509Certificates);
+ }
+ }
+
+ @Override
+ protected void createTransformsStructureForSignature(OutputProcessorChain subOutputProcessorChain, SignaturePartDef signaturePartDef) throws XMLStreamException, XMLSecurityException {
+ if (signaturePartDef.getTransformAlgo() != null) {
+ List<XMLSecAttribute> attributes = new ArrayList<XMLSecAttribute>(1);
+ attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, signaturePartDef.getTransformAlgo()));
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform, false, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform);
+ } else {
+ List<XMLSecAttribute> attributes = new ArrayList<XMLSecAttribute>(1);
+ attributes.add(createAttribute(XMLSecurityConstants.ATT_NULL_Algorithm, signaturePartDef.getC14nAlgo()));
+ createStartElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform, false, attributes);
+ createEndElementAndOutputAsEvent(subOutputProcessorChain, XMLSecurityConstants.TAG_dsig_Transform);
+ }
+ }
+
+ private static void flushBufferAndCallbackAfterTokenID(OutputProcessorChain outputProcessorChain,
+ AbstractBufferingOutputProcessor abstractBufferingOutputProcessor,
+ Deque<XMLSecEvent> xmlSecEventDeque
+ ) throws XMLStreamException, XMLSecurityException {
+ final Iterator<XMLSecEvent> xmlSecEventIterator = xmlSecEventDeque.descendingIterator();
+
+ String appendAfterThisTokenId = abstractBufferingOutputProcessor.getAppendAfterThisTokenId();
+
+ //append current header
+ if (appendAfterThisTokenId == null) {
+ abstractBufferingOutputProcessor.processHeaderEvent(outputProcessorChain);
+ } else {
+ //we have a dependent token. so we have to append the current header after the token
+ QName matchingElementName = null;
+
+ loop:
+ while (xmlSecEventIterator.hasNext()) {
+ XMLSecEvent xmlSecEvent = xmlSecEventIterator.next();
+
+ outputProcessorChain.reset();
+ outputProcessorChain.processEvent(xmlSecEvent);
+ switch (xmlSecEvent.getEventType()) {
+ //search for an element with a matching wsu:Id. this is our token
+ case XMLStreamConstants.START_ELEMENT:
+ XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
+ List<XMLSecAttribute> xmlSecAttributes = xmlSecStartElement.getOnElementDeclaredAttributes();
+ for (int i = 0; i < xmlSecAttributes.size(); i++) {
+ XMLSecAttribute xmlSecAttribute = xmlSecAttributes.get(i);
+ final QName attributeName = xmlSecAttribute.getName();
+ final String attributeValue = xmlSecAttribute.getValue();
+ if (XMLSecurityConstants.ATT_NULL_Id.equals(attributeName)
+ && appendAfterThisTokenId.equals(attributeValue)) {
+ matchingElementName = xmlSecStartElement.getName();
+ break loop;
+ }
+ }
+ break;
+ }
+ }
+
+ //we found the token and...
+ int level = 0;
+ loop:
+ while (xmlSecEventIterator.hasNext()) {
+ XMLSecEvent xmlSecEvent = xmlSecEventIterator.next();
+
+ outputProcessorChain.reset();
+ outputProcessorChain.processEvent(xmlSecEvent);
+ //...loop until we reach the token end element
+ switch (xmlSecEvent.getEventType()) {
+ case XMLStreamConstants.START_ELEMENT:
+ level++;
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ XMLSecEndElement xmlSecEndElement = xmlSecEvent.asEndElement();
+ if (level == 0 && xmlSecEndElement.getName().equals(matchingElementName)) {
+ //output now the current header
+ abstractBufferingOutputProcessor.processHeaderEvent(outputProcessorChain);
+ break loop;
+ }
+ level--;
+ break;
+ }
+ }
+ }
+
+ //loop through the rest of the document
+ while (xmlSecEventIterator.hasNext()) {
+ XMLSecEvent xmlSecEvent = xmlSecEventIterator.next();
+ outputProcessorChain.reset();
+ outputProcessorChain.processEvent(xmlSecEvent);
+ }
+ outputProcessorChain.reset();
+ }
+}
Added: santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java?rev=1355316&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java (added)
+++ santuario/xml-security-java/trunk/src/main/java/org/apache/xml/security/stax/impl/processor/output/XMLSignatureOutputProcessor.java Fri Jun 29 11:16:19 2012
@@ -0,0 +1,125 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.xml.security.stax.impl.processor.output;
+
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.events.Attribute;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.xml.security.stax.ext.OutputProcessorChain;
+import org.apache.xml.security.stax.ext.SecurePart;
+import org.apache.xml.security.stax.ext.XMLSecurityConstants;
+import org.apache.xml.security.stax.ext.XMLSecurityException;
+import org.apache.xml.security.stax.ext.stax.XMLSecAttribute;
+import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.ext.stax.XMLSecStartElement;
+import org.apache.xml.security.stax.impl.SignaturePartDef;
+import org.apache.xml.security.stax.impl.util.IDGenerator;
+
+/**
+ * An OutputProcessor for XML Signature.
+ */
+public class XMLSignatureOutputProcessor extends AbstractSignatureOutputProcessor {
+
+ private static final transient Log logger = LogFactory.getLog(XMLSignatureOutputProcessor.class);
+
+ public XMLSignatureOutputProcessor() throws XMLSecurityException {
+ super();
+ }
+
+ @Override
+ public void init(OutputProcessorChain outputProcessorChain) throws XMLSecurityException {
+ super.init(outputProcessorChain);
+ XMLSignatureEndingOutputProcessor signatureEndingOutputProcessor = new XMLSignatureEndingOutputProcessor(this);
+ signatureEndingOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
+ signatureEndingOutputProcessor.setAction(getAction());
+ signatureEndingOutputProcessor.init(outputProcessorChain);
+ }
+
+ @Override
+ public void processEvent(XMLSecEvent xmlSecEvent, OutputProcessorChain outputProcessorChain) throws XMLStreamException, XMLSecurityException {
+ if (xmlSecEvent.getEventType() == XMLStreamConstants.START_ELEMENT) {
+ XMLSecStartElement xmlSecStartElement = xmlSecEvent.asStartElement();
+
+ //avoid double signature when child elements matches too
+ if (getActiveInternalSignatureOutputProcessor() == null) {
+ SecurePart securePart = securePartMatches(xmlSecStartElement, outputProcessorChain, XMLSecurityConstants.SIGNATURE_PARTS);
+ if (securePart != null) {
+ logger.debug("Matched securePart for signature");
+
+ InternalSignatureOutputProcessor internalSignatureOutputProcessor = null;
+ try {
+ SignaturePartDef signaturePartDef = new SignaturePartDef();
+ if (securePart.getIdToSign() == null) {
+ signaturePartDef.setSigRefId(IDGenerator.generateID(null));
+ signaturePartDef.setC14nAlgo(getSecurityProperties().getSignatureCanonicalizationAlgorithm());
+
+ Attribute attribute = xmlSecStartElement.getAttributeByName(XMLSecurityConstants.ATT_NULL_Id);
+ if (attribute != null) {
+ signaturePartDef.setSigRefId(attribute.getValue());
+ } else {
+ List<XMLSecAttribute> attributeList = new ArrayList<XMLSecAttribute>(1);
+ attributeList.add(createAttribute(XMLSecurityConstants.ATT_NULL_Id, signaturePartDef.getSigRefId()));
+ xmlSecEvent = addAttributes(xmlSecStartElement, attributeList);
+ }
+ outputProcessorChain.getSecurityContext().put(
+ XMLSecurityConstants.PROP_APPEND_SIGNATURE_ON_THIS_ID,
+ signaturePartDef.getSigRefId()
+ );
+ } else {
+ signaturePartDef.setSigRefId(securePart.getIdToSign());
+ signaturePartDef.setC14nAlgo(getSecurityProperties().getSignatureCanonicalizationAlgorithm());
+ outputProcessorChain.getSecurityContext().put(
+ XMLSecurityConstants.PROP_APPEND_SIGNATURE_ON_THIS_ID,
+ securePart.getIdToSign()
+ );
+ }
+
+ getSignaturePartDefList().add(signaturePartDef);
+ internalSignatureOutputProcessor = new InternalSignatureOutputProcessor(signaturePartDef, xmlSecStartElement.getName());
+ internalSignatureOutputProcessor.setXMLSecurityProperties(getSecurityProperties());
+ internalSignatureOutputProcessor.setAction(getAction());
+ internalSignatureOutputProcessor.addAfterProcessor(XMLSignatureOutputProcessor.class.getName());
+ internalSignatureOutputProcessor.addBeforeProcessor(XMLSignatureEndingOutputProcessor.class.getName());
+ internalSignatureOutputProcessor.init(outputProcessorChain);
+
+ } catch (NoSuchAlgorithmException e) {
+ throw new XMLSecurityException(
+ XMLSecurityException.ErrorCode.UNSUPPORTED_ALGORITHM, "unsupportedKeyTransp",
+ e, "No such algorithm: " + getSecurityProperties().getSignatureAlgorithm()
+ );
+ } catch (NoSuchProviderException e) {
+ throw new XMLSecurityException(XMLSecurityException.ErrorCode.FAILURE, "noSecProvider", e);
+ }
+
+ setActiveInternalSignatureOutputProcessor(internalSignatureOutputProcessor);
+ }
+ }
+ }
+ outputProcessorChain.processEvent(xmlSecEvent);
+ }
+
+}
Modified: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/DSNamespaceContext.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/DSNamespaceContext.java?rev=1355316&r1=1355315&r2=1355316&view=diff
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/DSNamespaceContext.java (original)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/dom/DSNamespaceContext.java Fri Jun 29 11:16:19 2012
@@ -34,6 +34,7 @@ public class DSNamespaceContext implemen
public DSNamespaceContext() {
namespaceMap.put("ds", "http://www.w3.org/2000/09/xmldsig#");
+ namespaceMap.put("dsig", "http://www.w3.org/2000/09/xmldsig#");
}
public DSNamespaceContext(Map<String, String> namespaces) {
Added: santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureTest.java
URL: http://svn.apache.org/viewvc/santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureTest.java?rev=1355316&view=auto
==============================================================================
--- santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureTest.java (added)
+++ santuario/xml-security-java/trunk/src/test/java/org/apache/xml/security/test/stax/signature/SignatureTest.java Fri Jun 29 11:16:19 2012
@@ -0,0 +1,311 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.xml.security.test.stax.signature;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.security.Key;
+import java.security.Provider;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.List;
+import java.util.UUID;
+
+import javax.xml.namespace.QName;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamReader;
+import javax.xml.stream.XMLStreamWriter;
+import javax.xml.xpath.XPath;
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathFactory;
+
+import org.apache.xml.security.keys.KeyInfo;
+import org.apache.xml.security.signature.XMLSignature;
+import org.apache.xml.security.stax.config.Init;
+import org.apache.xml.security.stax.crypto.CryptoType;
+import org.apache.xml.security.stax.ext.SecurePart;
+import org.apache.xml.security.stax.ext.SecurityToken;
+import org.apache.xml.security.stax.ext.SecurityTokenProvider;
+import org.apache.xml.security.stax.ext.XMLSecurityConstants;
+import org.apache.xml.security.stax.ext.XMLSecurityException;
+import org.apache.xml.security.stax.ext.XMLSecurityProperties;
+import org.apache.xml.security.stax.ext.stax.XMLSecEvent;
+import org.apache.xml.security.stax.impl.DocumentContextImpl;
+import org.apache.xml.security.stax.impl.OutputProcessorChainImpl;
+import org.apache.xml.security.stax.impl.SecurityContextImpl;
+import org.apache.xml.security.stax.impl.XMLSecurityStreamWriter;
+import org.apache.xml.security.stax.impl.processor.output.FinalOutputProcessor;
+import org.apache.xml.security.stax.impl.processor.output.XMLSignatureOutputProcessor;
+import org.apache.xml.security.test.dom.DSNamespaceContext;
+import org.apache.xml.security.test.stax.utils.XMLSecEventAllocator;
+import org.apache.xml.security.test.stax.utils.XmlReaderToWriter;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+/**
+ * A set of test-cases for Signature creation.
+ */
+public class SignatureTest extends org.junit.Assert {
+
+ private XMLInputFactory xmlInputFactory;
+ private DocumentBuilderFactory documentBuilderFactory;
+
+ static {
+ try {
+ Class<?> c =
+ SignatureTest.class.getClassLoader().loadClass(
+ "org.bouncycastle.jce.provider.BouncyCastleProvider"
+ );
+ if (null == Security.getProvider("BC")) {
+ // Security.addProvider((Provider) c.newInstance());
+ Security.insertProviderAt((Provider) c.newInstance(), 1);
+ }
+ } catch (Throwable e) {
+ throw new RuntimeException("Adding BouncyCastle provider failed", e);
+ }
+ }
+
+ @Before
+ public void setUp() throws Exception {
+ Init.init(SignatureTest.class.getClassLoader().getResource("security-config.xml").toURI());
+ org.apache.xml.security.Init.init();
+
+ xmlInputFactory = XMLInputFactory.newInstance();
+ xmlInputFactory.setEventAllocator(new XMLSecEventAllocator());
+
+ documentBuilderFactory = DocumentBuilderFactory.newInstance();
+ documentBuilderFactory.setNamespaceAware(true);
+ documentBuilderFactory.setIgnoringComments(false);
+ documentBuilderFactory.setCoalescing(false);
+ documentBuilderFactory.setIgnoringElementContentWhitespace(false);
+ }
+
+ @Test
+ public void testSignatureCreation() throws Exception {
+ // Set up the Configuration
+ XMLSecurityProperties properties = new XMLSecurityProperties();
+ XMLSecurityConstants.Action[] actions =
+ new XMLSecurityConstants.Action[]{XMLSecurityConstants.SIGNATURE};
+ properties.setOutAction(actions);
+ properties.loadSignatureKeyStore(
+ this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray()
+ );
+ properties.setSignatureUser("transmitter");
+ properties.setSignatureAlgorithm("http://www.w3.org/2000/09/xmldsig#rsa-sha1");
+ properties.setSignatureCanonicalizationAlgorithm("http://www.w3.org/2001/10/xml-exc-c14n#");
+ properties.setSignatureDigestAlgorithm("http://www.w3.org/2000/09/xmldsig#sha1");
+
+ SecurePart securePart =
+ new SecurePart(new QName("urn:example:po", "PaymentInfo"), SecurePart.Modifier.Content);
+ properties.addSignaturePart(securePart);
+
+ // Set the key up
+ SecurityContextImpl securityContextImpl = new SecurityContextImpl();
+ Key key = properties.getSignatureCrypto().getPrivateKey("transmitter", "default");
+ CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
+ cryptoType.setAlias(properties.getSignatureUser());
+ X509Certificate[] x509Certificates = properties.getSignatureCrypto().getX509Certificates(cryptoType);
+
+ SignatureSecurityToken securityToken = new SignatureSecurityToken(key, x509Certificates);
+ String id = UUID.randomUUID().toString();
+ SignatureSecurityTokenProvider securityTokenProvider =
+ new SignatureSecurityTokenProvider(securityToken, id);
+ securityContextImpl.registerSecurityTokenProvider(id, securityTokenProvider);
+ securityContextImpl.put(XMLSecurityConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, id);
+ securityContextImpl.putAsMap(XMLSecurityConstants.SIGNATURE_PARTS, securePart.getName(), securePart);
+
+ final DocumentContextImpl documentContext = new DocumentContextImpl();
+ documentContext.setEncoding("UTF-8");
+ InputStream sourceDocument =
+ this.getClass().getClassLoader().getResourceAsStream(
+ "ie/baltimore/merlin-examples/merlin-xmlenc-five/plaintext.xml");
+
+ OutputProcessorChainImpl processorChain =
+ new OutputProcessorChainImpl(securityContextImpl, documentContext);
+ XMLSignatureOutputProcessor signatureOutputProcessor = new XMLSignatureOutputProcessor();
+ signatureOutputProcessor.setXMLSecurityProperties(properties);
+ signatureOutputProcessor.setAction(XMLSecurityConstants.SIGNATURE);
+ signatureOutputProcessor.init(processorChain);
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ FinalOutputProcessor finalOutputProcessor = new FinalOutputProcessor(baos, "UTF-8");
+ finalOutputProcessor.setXMLSecurityProperties(properties);
+ finalOutputProcessor.setAction(null);
+ finalOutputProcessor.init(processorChain);
+ processorChain.addProcessor(finalOutputProcessor);
+
+ XMLStreamWriter xmlStreamWriter = new XMLSecurityStreamWriter(processorChain);
+
+ XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
+ XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
+ xmlStreamWriter.close();
+
+ // System.out.println("Got:\n" + new String(baos.toByteArray(), "UTF-8"));
+ Document document =
+ documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
+
+ // Verify using DOM
+ verifyUsingDOM(document, x509Certificates[0], securePart);
+ }
+
+ /**
+ * Verify the document using DOM
+ */
+ private void verifyUsingDOM(
+ Document document,
+ X509Certificate cert,
+ SecurePart securePart
+ ) throws Exception {
+ XPathFactory xpf = XPathFactory.newInstance();
+ XPath xpath = xpf.newXPath();
+ xpath.setNamespaceContext(new DSNamespaceContext());
+
+ String expression = "//dsig:Signature[1]";
+ Element sigElement =
+ (Element) xpath.evaluate(expression, document, XPathConstants.NODE);
+ Assert.assertNotNull(sigElement);
+
+ expression = "//*[local-name()='" + securePart.getName().getLocalPart() + "']";
+ Element signedElement =
+ (Element)xpath.evaluate(expression, document, XPathConstants.NODE);
+ Assert.assertNotNull(signedElement);
+ signedElement.setIdAttributeNS(null, "Id", true);
+
+ XMLSignature signature = new XMLSignature(sigElement, "");
+ KeyInfo ki = signature.getKeyInfo();
+ Assert.assertNotNull(ki);
+
+ Assert.assertTrue(signature.checkSignatureValue(cert));
+ }
+
+ private static class SignatureSecurityToken implements SecurityToken {
+ private Key key;
+ private X509Certificate[] certs;
+
+ public SignatureSecurityToken(Key key, X509Certificate[] certs) {
+ this.key = key;
+ this.certs = certs;
+ }
+
+ public String getId() {
+ return null;
+ }
+
+
+ public Object getProcessor() {
+ return null;
+ }
+
+ public boolean isAsymmetric() {
+ return false;
+ }
+
+ public Key getSecretKey(
+ String algorithmURI, XMLSecurityConstants.KeyUsage keyUsage
+ ) throws XMLSecurityException {
+ return key;
+ }
+
+ public PublicKey getPublicKey(
+ String algorithmURI, XMLSecurityConstants.KeyUsage keyUsage
+ ) throws XMLSecurityException {
+ return null;
+ }
+
+ public X509Certificate[] getX509Certificates() throws XMLSecurityException {
+ return certs;
+ }
+
+ public void verify() throws XMLSecurityException {
+ }
+
+ public SecurityToken getKeyWrappingToken() {
+ return null;
+ }
+
+ public XMLSecurityConstants.TokenType getTokenType() {
+ return null;
+ }
+
+ @Override
+ public List<QName> getElementPath() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public XMLSecEvent getXMLSecEvent() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public List<SecurityToken> getWrappedTokens()
+ throws XMLSecurityException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void addWrappedToken(SecurityToken securityToken) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void addTokenUsage(TokenUsage tokenUsage)
+ throws XMLSecurityException {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public List<TokenUsage> getTokenUsages() {
+ // TODO Auto-generated method stub
+ return null;
+ }
+ };
+
+ private static class SignatureSecurityTokenProvider implements SecurityTokenProvider {
+ private SecurityToken token;
+ private String id;
+
+ public SignatureSecurityTokenProvider(SecurityToken token, String id) {
+ this.token = token;
+ }
+
+ @Override
+ public String getId() {
+ return id;
+ }
+
+ @Override
+ public SecurityToken getSecurityToken() throws XMLSecurityException {
+ return token;
+ }
+ };
+
+
+}
\ No newline at end of file