Uploaded image for project: 'WSS4J'
  1. WSS4J
  2. WSS-618

Cannot create signature which includes KeyInfo

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 2.2.0
    • 2.1.12, 2.2.1
    • WSS4J Core
    • None
    • Using 2.2.0 in Apache CXF with WSS4JStaxOutInterceptor.

    Description

      I am using WSS4j inside CXF, using the WSS4JStaxOutInterceptor, to generate a XML Signature. This signature must include the KeyInfo (customer requires Body and KeyInfo to be signed).

      My configuration includes:

              final Map< String, Object > outProps = new HashMap<>();
              outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE);
      
              // Crypto configuration left out
      
              outProps.put(WSHandlerConstants.SIG_ALGO, WSSConstants.NS_XMLDSIG_RSASHA256);
              outProps.put(WSHandlerConstants.SIG_DIGEST_ALGO, WSSConstants.NS_XENC_SHA256);
              outProps.put(WSHandlerConstants.SIG_C14N_ALGO, WSSConstants.NS_C14N_EXCL_OMIT_COMMENTS);
              outProps.put(WSHandlerConstants.SIG_KEY_ID, "IssuerSerial");
              
              // Using defaults, same as: "{Content}{http://schemas.xmlsoap.org/soap/envelope/}Body;{Content}{http://www.w3.org/2000/09/xmldsig#}KeyInfo"
              outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "Body;{}{" + WSSConstants.NS_DSIG + "}KeyInfo");      
      
              jaxWsFactory.getOutInterceptors().add(new WSS4JStaxOutInterceptor(outProps));
      

      This results in an exception:

      Caused by: org.apache.xml.security.exceptions.XMLSecurityException: Part to sign not found: {http://www.w3.org/2000/09/xmldsig#}KeyInfo
      	at org.apache.xml.security.stax.impl.processor.output.AbstractSignatureOutputProcessor.verifySignatureParts(AbstractSignatureOutputProcessor.java:155)
      	at org.apache.xml.security.stax.impl.processor.output.AbstractSignatureOutputProcessor.doFinalInternal(AbstractSignatureOutputProcessor.java:86)
      	at org.apache.wss4j.stax.impl.processor.output.WSSSignatureOutputProcessor.processEvent(WSSSignatureOutputProcessor.java:138)
      	at org.apache.xml.security.stax.ext.AbstractOutputProcessor.processNextEvent(AbstractOutputProcessor.java:133)
      	at org.apache.xml.security.stax.impl.OutputProcessorChainImpl.processEvent(OutputProcessorChainImpl.java:212)
      	at org.apache.xml.security.stax.impl.XMLSecurityStreamWriter.chainProcessEvent(XMLSecurityStreamWriter.java:62)
      	... 67 common frames omitted
      

      If I change the SIGNATURE_PARTS to only "Body", things work as expected, and a KeyInfo is included (but ofcourse not signed).

      I assume this is because of the order WSS4J does things, it first creates/checks all the parts to be signed. And only after that creates the KeyInfo structure.

      Debugging I can see that the following steps occur in this order:
      Checking the parts (and also creating the references or so, I think):

      Thread [main] (Suspended (entry into method verifySignatureParts in AbstractSignatureOutputProcessor))	
      	owns: PhaseInterceptorChain  (id=93)	
      	WSSSignatureOutputProcessor(AbstractSignatureOutputProcessor).verifySignatureParts(OutputProcessorChain) line: 137	
      	WSSSignatureOutputProcessor(AbstractSignatureOutputProcessor).doFinalInternal(OutputProcessorChain) line: 86	
      	WSSSignatureOutputProcessor.processEvent(XMLSecEvent, OutputProcessorChain) line: 138	
      	WSSSignatureOutputProcessor(AbstractOutputProcessor).processNextEvent(XMLSecEvent, OutputProcessorChain) line: 133	
      	OutputProcessorChainImpl.processEvent(XMLSecEvent) line: 212	
      	XMLSecurityStreamWriter.chainProcessEvent(XMLSecEvent) line: 62	
      	XMLSecurityStreamWriter.outputOpenStartElement() line: 83	
      	XMLSecurityStreamWriter.writeStartElement(String, String, String) line: 116	
      	XMLStreamWriterOutput.beginStartTag(int, String) line: 103	
      	XMLStreamWriterOutput(XmlOutputAbstractImpl).beginStartTag(Name) line: 87	
      	ForkXmlOutput.beginStartTag(Name) line: 65	
      	NamespaceContextImpl$Element.startElement(XmlOutput, Object) line: 481	
      	XMLSerializer.endNamespaceDecls(Object) line: 273	
      	XMLSerializer.childAsXsiType(Object, String, JaxBeanInfo, boolean) line: 668	
      	SingleElementNodeProperty<BeanT,ValueT>.serializeBody(BeanT, XMLSerializer, Object) line: 143	
      	ElementBeanInfoImpl$1.serializeBody(JAXBElement, XMLSerializer, Object) line: 145	
      	ElementBeanInfoImpl$1.serializeBody(Object, XMLSerializer, Object) line: 115	
      	ElementBeanInfoImpl.serializeBody(JAXBElement, XMLSerializer) line: 317	
      	ElementBeanInfoImpl.serializeRoot(JAXBElement, XMLSerializer) line: 324	
      	ElementBeanInfoImpl.serializeRoot(Object, XMLSerializer) line: 60	
      	XMLSerializer.childAsRoot(Object) line: 479	
      	MarshallerImpl.write(Object, XmlOutput, Runnable) line: 308	
      	MarshallerImpl.marshal(Object, XMLStreamWriter) line: 163	
      	JAXBEncoderDecoder.writeObject(Marshaller, Object, Object) line: 614	
      	JAXBEncoderDecoder.marshall(Marshaller, Object, MessagePartInfo, Object) line: 243	
      	DataWriterImpl<T>.write(Object, MessagePartInfo, T) line: 232	
      	BareOutInterceptor(AbstractOutDatabindingInterceptor).writeParts(Message, Exchange, BindingOperationInfo, MessageContentsList, List<MessagePartInfo>) line: 137	
      	BareOutInterceptor.handleMessage(Message) line: 68	
      	PhaseInterceptorChain.doIntercept(Message) line: 308	
      	ClientImpl.doInvoke(ClientCallback, BindingOperationInfo, Object[], Map<String,Object>, Exchange) line: 516	
      

      Creating the KeyInfo structure:

      Thread [main] (Suspended (entry into method createKeyInfoStructureForSignature in WSSSignatureEndingOutputProcessor))	
      	owns: PhaseInterceptorChain  (id=93)	
      	WSSSignatureEndingOutputProcessor.createKeyInfoStructureForSignature(OutputProcessorChain, OutboundSecurityToken, boolean) line: 91	
      	WSSSignatureEndingOutputProcessor(AbstractSignatureEndingOutputProcessor).processHeaderEvent(OutputProcessorChain) line: 216	
      	WSSSignatureEndingOutputProcessor.processHeaderEvent(OutputProcessorChain) line: 77	
      	WSSSignatureEndingOutputProcessor(AbstractBufferingOutputProcessor).flushBufferAndCallbackAfterHeader(OutputProcessorChain, Deque<XMLSecEvent>) line: 66	
      	WSSSignatureEndingOutputProcessor.flushBufferAndCallbackAfterHeader(OutputProcessorChain, Deque<XMLSecEvent>) line: 284	
      	WSSSignatureEndingOutputProcessor(AbstractBufferingOutputProcessor).doFinal(OutputProcessorChain) line: 52	
      	OutputProcessorChainImpl.doFinal() line: 220	
      	XMLSecurityStreamWriter.close() line: 190	
      	WSS4JStaxOutInterceptor$WSS4JStaxOutInterceptorInternal.handleMessageInternal(Message) line: 336	
      	WSS4JStaxOutInterceptor$WSS4JStaxOutInterceptorInternal.handleMessage(Message) line: 322	
      	PhaseInterceptorChain.doIntercept(Message) line: 308	
      	ClientImpl.doInvoke(ClientCallback, BindingOperationInfo, Object[], Map<String,Object>, Exchange) line: 516	
      

      I thought mayby this would be a limitation of the Stax way of working (streaming over DOM), but in a quick test the DOM based wss4j implementation also gives a similar exception, not being able to find the part to sign:

      Caused by: org.apache.wss4j.common.ext.WSSecurityException: Element to encrypt/sign not found: http://www.w3.org/2000/09/xmldsig#, KeyInfo
      	at org.apache.wss4j.dom.message.WSSecSignatureBase.addReferencesToSign(WSSecSignatureBase.java:184)
      	... 52 common frames omitted
      

      Using OPTIONAL_SIGNATURE_PARTS instead of SIGNATURE_PARTS also doesn't solve the issue, in that case the KeyInfo is simply not signed, again both for the DOM as Stax version.

      Attachments

        Issue Links

          Activity

            People

              coheigea Colm O hEigeartaigh
              cranphin c
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: