I'm using Apache CXF + WS-Security in my project when connecting to the server.
When server's response is received I must validate the signature of SignatureConfirmation, Timestamp, SOAP-body with server's public key, which is included as BinarySecurityToken in SOAP header.
After that I need to decrypt the symmetrical key with my own certificate's private key and eventually decrypt the SOAP body.
Here is the diagram with the request-flow:
How should I configure my WSS4JInInterceptor to do that?
Here is what I have now:
// for outgoing messages: Signature and Timestamp validation
outProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.TIMESTAMP);
outProps.put(WSHandlerConstants.USER, "sss");
outProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientKeystorePasswordCallbackHandler.class.getName());
outProps.put(WSHandlerConstants.SIG_PROP_FILE, "client_sec.properties");
outProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
outProps.put(WSHandlerConstants.SIGNATURE_PARTS, "{}{http://www.w3.org/2003/05/soap-envelope}Body;{}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp;{}{http://kontaktinfo.difi.no/wsdl/oppslagstjeneste-16-02}Oppslagstjenesten}");
outProps.put(WSHandlerConstants.SIG_ALGO, "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
outProps.put(WSHandlerConstants.SIG_DIGEST_ALGO, "http://www.w3.org/2001/04/xmlenc#sha256");
// for incoming messages: Signature and Timestamp validation. Response is Encrypted
inProps.put(WSHandlerConstants.ACTION, WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.ENCRYPT);
inProps.put(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
inProps.put(WSHandlerConstants.PW_CALLBACK_CLASS, ClientKeystorePasswordCallbackHandler.class.getName());
inProps.put(WSHandlerConstants.SIG_PROP_FILE, "server_sec.properties");
inProps.put(WSHandlerConstants.DEC_PROP_FILE, "client_sec.properties");
wss4JInInterceptor = new WSS4JInInterceptor(inProps);
wss4JOutInterceptor = new WSS4JOutInterceptor(outProps);
server_sec.properties
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=jks
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.keystore.alias=test
org.apache.ws.security.crypto.merlin.file=certs/server.jks
client_sec.properties:
org.apache.ws.security.crypto.provider=org.apache.ws.security.components.crypto.Merlin
org.apache.ws.security.crypto.merlin.keystore.type=PKCS12
org.apache.ws.security.crypto.merlin.keystore.password=changeit
org.apache.ws.security.crypto.merlin.keystore.alias=sss
org.apache.ws.security.crypto.merlin.file=certs/sss_client.p12
After I receive the response I get the error:
SEVERE: Servlet.service() for servlet [rest] in context with path [] threw exception [Request processing failed; nested exception is javax.xml.ws.soap.SOAPFaultException: Error during certificate path validation: No trusted certs found] with root cause
org.apache.wss4j.common.ext.WSSecurityException: Error during certificate path validation: No trusted certs found
at org.apache.wss4j.common.crypto.Merlin.verifyTrust(Merlin.java:780)
at org.apache.wss4j.dom.validate.SignatureTrustValidator.verifyTrustInCerts(SignatureTrustValidator.java:108)
at org.apache.wss4j.dom.validate.SignatureTrustValidator.validate(SignatureTrustValidator.java:64)
at org.apache.wss4j.dom.processor.SignatureProcessor.handleToken(SignatureProcessor.java:189)
at org.apache.wss4j.dom.engine.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:344)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessageInternal(WSS4JInInterceptor.java:280)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:184)
at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:93)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.onMessage(ClientImpl.java:798)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponseInternal(HTTPConduit.java:1670)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.handleResponse(HTTPConduit.java:1551)
at org.apache.cxf.transport.http.HTTPConduit$WrappedOutputStream.close(HTTPConduit.java:1348)
at org.apache.cxf.io.CacheAndWriteOutputStream.postClose(CacheAndWriteOutputStream.java:56)
at org.apache.cxf.io.CachedOutputStream.close(CachedOutputStream.java:216)
at org.apache.cxf.transport.AbstractConduit.close(AbstractConduit.java:56)
at org.apache.cxf.transport.http.HTTPConduit.close(HTTPConduit.java:651)
at org.apache.cxf.interceptor.MessageSenderInterceptor$MessageSenderEndingInterceptor.handleMessage(MessageSenderInterceptor.java:62)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:308)
at org.apache.cxf.endpoint.ClientImpl.doInvoke(ClientImpl.java:514)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:423)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:324)
at org.apache.cxf.endpoint.ClientImpl.invoke(ClientImpl.java:277)
at org.apache.cxf.frontend.ClientProxy.invokeSync(ClientProxy.java:96)
at org.apache.cxf.jaxws.JaxWsClientProxy.invoke(JaxWsClientProxy.java:139)
at com.sun.proxy.$Proxy74.getPeople(Unknown Source)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:956)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:423)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1079)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:625)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:745)
The first problem I see is CXF expects server certificate to be a keystone file, but I have it as Binary Security Token included in the response. Extracting it into a file is not an option, of course.
How should I configure my InInterceptor so it can verify and decrypt server's response?
UPDATE 1:
root CA certificate is added to
JRE/lib/security/cacertsIntermediate certificate is in the keystore used by the in-interceptor
Here is the server response I'm trying to verify and decrypt:
<?xml version="1.0" encoding="UTF-8"?>
<env:Envelope xmlns:env="http://www.w3.org/2003/05/soap-envelope">
<env:Header>
<wsse:Security 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" env:mustUnderstand="true">
<xenc:EncryptedKey xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="EK-66D388AF0DD8D8AE061458643455700833237">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference>
<ds:X509Data>
<ds:X509IssuerSerial>
<ds:X509IssuerName>CN=Buypass Class 3 Test4 CA 3,O=Buypass AS-983163327,C=NO</ds:X509IssuerName>
<ds:X509SerialNumber>1111111111111111111</ds:X509SerialNumber>
</ds:X509IssuerSerial>
</ds:X509Data>
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>VSZMFYsHgVWPhhhBjcmITh2ElsViaRhmyVcLlyC9/iAh/gpIT1mhqocYRr3uDUZUVjNZba8wfRbVYTPAz/Kxix7faZ8+F23ANyhhKmrwxgn2SJdOVjYRYiVZZ/lgufYO4jFDnbkDjHeNxY6FZ/nxdB25OX18v5sWPkXtJQLKm3wQS6gQ8xc7K48lnIZDiKDGs0AyY4wCQ8rd0sI/odFma9h7661rs9Ei0WtzWU8reuhd/YGcaShY7qNnG/EguItnd4H4uEpgH09tCCge3R3vIw7LYK+qa5n97UVKe6ZZcRENZgyDR0PYx7bA+wcmGbHgZUivbc3FhJGwvXjGUu+3Xw==</xenc:CipherValue>
</xenc:CipherData>
<xenc:ReferenceList>
<xenc:DataReference URI="#ED-66D388AF0DD8D8AE061458643455700833238" />
</xenc:ReferenceList>
</xenc:EncryptedKey>
<wsse:BinarySecurityToken EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" wsu:Id="X509-66D388AF0DD8D8AE061458643455693833232">MIIFDzCCA/egAwIBAgILCDNWTvJPbvLPzFQwDQYJKoZIhvcNAQELBQAwSzELMAu390STHWF1hjeDUZ8ep4u3cO0bwKHsdkrp/JIWQ6q8PpIJHcCDrz/tIKn2JLpxbQe9AR6KWDDzgfyRxoCyulOcnXoVH+CeSfieQ3WapR5VymxpPDA+jC6fccPfBDpKrOso4WpFFvwJbyEhxDAgJAXzwx1R3CrTFAfku8cck0h3v5E4</wsse:BinarySecurityToken>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="SIG-66D388AF0DD8D8AE061458643455696833236">
<ds:SignedInfo>
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
<ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" />
<ds:Reference URI="#TS-66D388AF0DD8D8AE061458643455693833231">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>vUNvEQQFUqrUScQTwDrfVl+SEd/T5f/8RegkbE/Hcig=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#id-66D388AF0DD8D8AE061458643455693833235">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>dv6BjR/TX8x1eYnlLyHCZQCQcdpOQ8o8CDE5mmCEYCw=</ds:DigestValue>
</ds:Reference>
<ds:Reference URI="#SC-66D388AF0DD8D8AE061458643455693833230">
<ds:Transforms>
<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" />
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" />
<ds:DigestValue>+F0GP7N7OlRpKR1yMRHn7F8ZYhCoPqDeDvjNMiQ5bHU=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>EAclVc0VHMFZtPFGCzwGrvMhp4W4Rmzf2Jke0oZeRcVKNpx88FSCfiCaEx5EaSs8zisbm8dQ7tDSWGnOWgVw1i6S0BXrq5g7Vn2+YZxmKJdJVxwtFAvCl9mXWF7gSgPVX8OYPmSFQ7I9cGaUr8/Sh5o3qClmNez/H4jOSgGXx6zXHqqG3FSkgaXaf0dfY6CgybTff2WG5dfnIdP4tfvllbNfzJa6Lgx8gsGZfG6J1c71mhBSo4ogejW64D0yjWBSGIdsrnAvgZZpXUs3ecR1za+GGUb9UhKLYoaiZZ1XO5fwOZM9TwXkmOwIG8mLbiXMnbsVmC5lyI5ARyZzrDRTmg==</ds:SignatureValue>
<ds:KeyInfo Id="KI-66D388AF0DD8D8AE061458643455693833233">
<wsse:SecurityTokenReference wsu:Id="STR-66D388AF0DD8D8AE061458643455693833234">
<wsse:Reference URI="#X509-66D388AF0DD8D8AE061458643455693833232" ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
</ds:Signature>
<wsu:Timestamp wsu:Id="TS-66D388AF0DD8D8AE061458643455693833231">
<wsu:Created>2016-03-22T10:44:15.693Z</wsu:Created>
<wsu:Expires>2016-03-22T10:45:15.693Z</wsu:Expires>
</wsu:Timestamp>
<wsse11:SignatureConfirmation xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" Value="1uzncWE+stuYWDjMt6dPyFpt1UAiyFjvWlA/sSV+2y2dqJ+GmE9/izZqgZ07Nhz1+TFnjX8h/ZvjbSpZEk9H280zJXYP8mVk87rz5qOD8ivt2T1m4zOIMNIvtvCwAGSN+ozTA7HWuzRELbMjiHbFwsLsBXtmmO0hngytyMyFvcnxThKcfb2wAsyhW6pnVX9Fu9OHKLIoktdYKX5ofXWxu8aH6OjfnbexKIa6URATpQIuLjPmQFh6t9YZcBnpHJuKcydIZBQGKEd9h41crVDrVQJ1YEGGmX4XKhLaEOFx/i+kMMjFfrowzodLxMx0vKW73vvhydv3BIWyWROo6X4JDg==" wsu:Id="SC-66D388AF0DD8D8AE061458643455693833230" />
</wsse:Security>
</env:Header>
<env:Body xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd" wsu:Id="id-66D388AF0DD8D8AE061458643455693833235">
<xenc:EncryptedData xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" Id="ED-66D388AF0DD8D8AE061458643455700833238" Type="http://www.w3.org/2001/04/xmlenc#Content">
<xenc:EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes256-cbc" />
<ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<wsse:SecurityTokenReference xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:wsse11="http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd" wsse11:TokenType="http://docs.oasis-open.org/wss/oasis-wss-soap-message-security-1.1#EncryptedKey">
<wsse:Reference URI="#EK-66D388AF0DD8D8AE061458643455700833237" />
</wsse:SecurityTokenReference>
</ds:KeyInfo>
<xenc:CipherData>
<xenc:CipherValue>Zl4kpoGYlFRXJ453SZIHxR4VVdzMCfnfTQogResKRu1PO8vHt6Azkc3/q0R0duPdUuttwQDGOUls+jw==</xenc:CipherValue>
</xenc:CipherData>
</xenc:EncryptedData>
</env:Body>
</env:Envelope>
