[ https://issues.apache.org/jira/browse/WSS-618?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16251524#comment-16251524 ]
J.Cranendonk commented on WSS-618: ---------------------------------- Hi! Thank you very much for your effort! I have tried the new code, sadly it doesn't work yet.. The stack trace is at the end of the comment, I think what is happening is that your addition is to WSSecSignature.build(Crypto cr). Based on the comment on the code this is an older method no longer used, if I look at the stack trace, this now flows through SignatureAction.execute(...), where there is a similar code block (look for "STRTransform"). I've tried to apply the same code to SignatureAction in an ugly way :) Which seems to mostly work! I've added a patch for that below the stack trace :) The only problem I now run into is that in verifying I get a complaint about "org.apache.wss4j.common.ext.WSSecurityException: Referenced security token could not be retrieved". Looking at the XML I see this: <wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" *wsu:Id="STR-f0836798-d1fb-4b4c-a92f-60c5dfae811b"*> I think what might happen is that the STR-.. id is replaced on KeyInfo or so? I have no idea what the STR id is or why it's there tbh. :) {noformat} 14-11-2017 15:50:21.192 [35m[SimpleAsyncTaskExecutor-1][0;39m [31mWARN [0;39m o.a.cxf.phase.PhaseInterceptorChain.doLog - Interceptor for {urn:nl-gdi-eid:1.0:webservices}BSNKActivatePortService#{urn:nl-gdi-eid:1.0:webservices}BSNK_ProvidePP_PPCAOptimized has thrown exception, unwinding now org.apache.cxf.binding.soap.SoapFault: Security processing failed. at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessageInternal(WSS4JOutInterceptor.java:272) at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessage(WSS4JOutInterceptor.java:136) at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessage(WSS4JOutInterceptor.java:123) at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308) at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:516) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:425) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:326) at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:279) at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96) at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:139) at com.sun.proxy.$Proxy125.bsnkProvidePPPPCAOptimized(Unknown Source) at com.idemia.efunc.ih.bsnk.ws.BsnkWebServiceClient.send(BsnkWebServiceClient.java:89) at sun.reflect.GeneratedMethodAccessor58.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.expression.spel.support.ReflectiveMethodExecutor.execute(ReflectiveMethodExecutor.java:113) at org.springframework.expression.spel.ast.MethodReference.getValueInternal(MethodReference.java:102) at org.springframework.expression.spel.ast.MethodReference.access$000(MethodReference.java:49) at org.springframework.expression.spel.ast.MethodReference$MethodValueRef.getValue(MethodReference.java:347) at org.springframework.expression.spel.ast.CompoundExpression.getValueInternal(CompoundExpression.java:88) at org.springframework.expression.spel.ast.SpelNodeImpl.getTypedValue(SpelNodeImpl.java:131) at org.springframework.expression.spel.standard.SpelExpression.getValue(SpelExpression.java:360) at org.springframework.integration.util.AbstractExpressionEvaluator.evaluateExpression(AbstractExpressionEvaluator.java:169) at org.springframework.integration.util.MessagingMethodInvokerHelper.processInternal(MessagingMethodInvokerHelper.java:319) at org.springframework.integration.util.MessagingMethodInvokerHelper.process(MessagingMethodInvokerHelper.java:155) at org.springframework.integration.handler.MethodInvokingMessageProcessor.processMessage(MethodInvokingMessageProcessor.java:93) at org.springframework.integration.handler.ServiceActivatingHandler.handleRequestMessage(ServiceActivatingHandler.java:89) at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:109) at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:127) at org.springframework.integration.dispatcher.AbstractDispatcher.tryOptimizedDispatch(AbstractDispatcher.java:116) at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:148) at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:121) at org.springframework.integration.amqp.channel.AbstractSubscribableAmqpChannel$DispatchingMessageListener.onMessage(AbstractSubscribableAmqpChannel.java:293) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:891) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:782) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$001(SimpleMessageListenerContainer.java:102) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$1.invokeListener(SimpleMessageListenerContainer.java:198) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.invokeListener(SimpleMessageListenerContainer.java:1311) at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:752) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1254) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:1224) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$1600(SimpleMessageListenerContainer.java:102) at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1470) at java.lang.Thread.run(Thread.java:745) Caused by: org.apache.wss4j.common.ext.WSSecurityException: Error during Signature: at org.apache.wss4j.dom.action.SignatureAction.execute(SignatureAction.java:163) at org.apache.wss4j.dom.handler.WSHandler.doSenderAction(WSHandler.java:238) at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor.access$100(WSS4JOutInterceptor.java:55) at org.apache.cxf.ws.security.wss4j.WSS4JOutInterceptor$WSS4JOutInterceptorInternal.handleMessageInternal(WSS4JOutInterceptor.java:264) ... 43 common frames omitted Caused by: org.apache.wss4j.common.ext.WSSecurityException: Cannot setup signature data structure at org.apache.wss4j.dom.message.WSSecSignatureBase.addReferencesToSign(WSSecSignatureBase.java:220) at org.apache.wss4j.dom.message.WSSecSignature.addReferencesToSign(WSSecSignature.java:424) at org.apache.wss4j.dom.action.SignatureAction.execute(SignatureAction.java:149) ... 46 common frames omitted 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) ... 48 common frames omitted {noformat} {noformat} Index: src/main/java/org/apache/wss4j/dom/action/SignatureAction.java =================================================================== --- src/main/java/org/apache/wss4j/dom/action/SignatureAction.java (revision 1815207) +++ src/main/java/org/apache/wss4j/dom/action/SignatureAction.java (working copy) @@ -24,6 +24,9 @@ import javax.security.auth.callback.CallbackHandler; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dom.DOMCryptoContext; + import org.apache.wss4j.common.SecurityActionToken; import org.apache.wss4j.common.SignatureActionToken; import org.apache.wss4j.common.WSEncryptionPart; @@ -34,6 +37,7 @@ import org.apache.wss4j.dom.handler.WSHandler; import org.apache.wss4j.dom.message.WSSecSignature; import org.apache.wss4j.dom.util.WSSecurityUtil; +import javax.xml.crypto.dom.DOMStructure; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; @@ -109,6 +113,21 @@ for (WSEncryptionPart part : signatureToken.getParts()) { if ("STRTransform".equals(part.getName()) && part.getId() == null) { part.setId(wsSign.getSecurityTokenReferenceURI()); + } else if ("KeyInfo".equals(part.getName()) && WSConstants.SIG_NS.equals(part.getNamespace()) + && part.getElement() == null) { + // Special code to sign the KeyInfo - we have to marshal the KeyInfo to a DOM Element + // before the signing process + Element parent = wsSign.getSecurityTokenReference().getElement().getOwnerDocument().createElement + DOMCryptoContext cryptoContext = new DOMCryptoContext() { + }; + cryptoContext.putNamespacePrefix(WSConstants.SIG_NS, WSConstants.SIG_PREFIX); + try { + wsSign.getKeyInfo().marshal(new DOMStructure(parent), cryptoContext); + } catch (MarshalException ex) { + //LOG.error(ex.getMessage(), ex); + throw new WSSecurityException(WSSecurityException.ErrorCode.FAILED_SIGNATURE, ex); + } + part.setElement((Element) parent.getFirstChild()); } else if (reqData.isAppendSignatureAfterTimestamp() && WSConstants.WSU_NS.equals(part.getNamespace()) && "Timestamp".equals(part.getName())) { Index: src/main/java/org/apache/wss4j/dom/message/WSSecSignature.java =================================================================== --- src/main/java/org/apache/wss4j/dom/message/WSSecSignature.java (revision 1815207) +++ src/main/java/org/apache/wss4j/dom/message/WSSecSignature.java (working copy) @@ -121,7 +121,9 @@ super(doc); init(provider); } - +public KeyInfo getKeyInfo() { + return keyInfo; +} private void init(Provider provider) { if (provider == null) { // Try to install the Santuario Provider - fall back to the JDK provider if this does {noformat} > Cannot create signature which includes KeyInfo > ---------------------------------------------- > > Key: WSS-618 > URL: https://issues.apache.org/jira/browse/WSS-618 > Project: WSS4J > Issue Type: Bug > Components: WSS4J Core > Affects Versions: 2.2.0 > Environment: Using 2.2.0 in Apache CXF with WSS4JStaxOutInterceptor. > Reporter: J.Cranendonk > Assignee: Colm O hEigeartaigh > Fix For: 2.1.12, 2.2.1 > > > 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: > {noformat} > 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)); > {noformat} > This results in an exception: > {noformat} > 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 > {noformat} > 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): > {noformat} > 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 > {noformat} > Creating the KeyInfo structure: > {noformat} > 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 > {noformat} > 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: > {noformat} > 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 > {noformat} > 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. -- This message was sent by Atlassian JIRA (v6.4.14#64029) --------------------------------------------------------------------- To unsubscribe, e-mail: dev-unsubscr...@ws.apache.org For additional commands, e-mail: dev-h...@ws.apache.org