You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@cxf.apache.org by "Ján Ondrušek (JIRA)" <ji...@apache.org> on 2014/04/10 09:26:15 UTC

[jira] [Comment Edited] (CXF-5679) WS-S after upgrade fails with org.apache.ws.security.WSSecurityException: The signature or decryption was invalid

    [ https://issues.apache.org/jira/browse/CXF-5679?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=13965085#comment-13965085 ] 

Ján Ondrušek edited comment on CXF-5679 at 4/10/14 7:24 AM:
------------------------------------------------------------

We use in out interceptors + Spring to configure CXF:

web.xml
{code:xml}
<servlet>
	<servlet-name>cxf</servlet-name>
	<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
{code}

cxf-servlet.xml
{code:xml}
<jaxws:endpoint id="cxfEndpoint" address="/" implementor="#endpoint">
	<jaxws:outInterceptors>
		<ref bean="outgoingSecurityInterceptor"/>
	</jaxws:outInterceptors>
	<jaxws:inInterceptors>
		<ref bean="cryptoCoverageChecker"/>
		<ref bean="incomingSecurityInterceptor"/>
	</jaxws:inInterceptors>
</jaxws:endpoint>
{code}

Spring JavaConfig:
{code:java}
	public static final String KEYSTORE_SERVICE_NAME = "org.apache.ws.security.crypto.merlin.keystore.alias";
	public static final String KEYSTORE_SERVICE_PASSWORD = "keystore.service.password";
	public static final String KEYSTORE_PROPERTIES = "keystoreProperties";

	private static final CoverageType TYPE_SIGNED = CryptoCoverageUtil.CoverageType.SIGNED;
	private static final CoverageScope SCOOPED_ELEMENT = CryptoCoverageUtil.CoverageScope.ELEMENT;

	private static final String X_PATH_BODY_VERIFIER = "/soap:Envelope/soap:Body";
	private static final String X_PATH_TIMESTAMP_VERIFIER = "/soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp";

	@Bean
	@Qualifier(KEYSTORE_PROPERTIES)
	public Properties getProperties() {
		return PropertiesLoaderUtils.loadProperties(...);
	}

	@Bean
	public Interceptor<SoapMessage> cryptoCoverageChecker() {
		Map<String, String> prefixes = Maps.newHashMap();
		prefixes.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");
		prefixes.put("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
		prefixes.put("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

		List<XPathExpression> xPaths = Lists.newArrayList();
		xPaths.add(bodyVerifier());
		xPaths.add(timestampVerifier());

		return new CryptoCoverageChecker(prefixes, xPaths);
	}

	@Bean
	public CryptoCoverageChecker.XPathExpression bodyVerifier() {
		return new CryptoCoverageChecker.XPathExpression(X_PATH_BODY_VERIFIER, TYPE_SIGNED, SCOOPED_ELEMENT);
	}

	@Bean
	public CryptoCoverageChecker.XPathExpression timestampVerifier() {
		return new CryptoCoverageChecker.XPathExpression(X_PATH_TIMESTAMP_VERIFIER, TYPE_SIGNED, SCOOPED_ELEMENT);
	}

	@Bean
	public Interceptor<SoapMessage> incomingSecurityInterceptor() {
		Map<String, Object> properties = Maps.newHashMap();
		properties.putAll(getCommonWSSProperties());
		return new WSS4JInInterceptor(properties);
	}

	@Bean
	public Interceptor<SoapMessage> outgoingSecurityInterceptor() {
		Map<String, Object> properties = Maps.newHashMap();
		properties.put(WSHandlerConstants.USER, getKeystoreProperty(KEYSTORE_SERVICE_NAME));
		properties.put(WSHandlerConstants.ENCRYPTION_USER, "useReqSigCert");
		properties.putAll(getCommonWSSProperties());
		properties.put(
				WSHandlerConstants.SIGNATURE_PARTS,
				"{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
		return new WSS4JOutInterceptor(properties);
	}

	@Bean
	public ServiceKeystorePasswordCallback passwordCallback() {
		Map<String, String> credentials = Maps.newHashMap();
		credentials.put(getKeystoreProperty(KEYSTORE_SERVICE_NAME), getKeystoreProperty(KEYSTORE_SERVICE_PASSWORD));
		CredentialsHolder credentialsHolder = new CredentialsHolder(credentials);
		return new ServiceKeystorePasswordCallback(credentialsHolder);
	}

	private String getKeystoreProperty(String key) {
		return getProperties().getProperty(key);
	}

	private Map<String, Object> getCommonWSSProperties() {
		Map<String, Object> properties = Maps.newHashMap();
		properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE);
		properties.put(WSHandlerConstants.SIG_PROP_REF_ID, KEYSTORE_PROPERTIES);
		properties.put(WSHandlerConstants.ENC_PROP_REF_ID, KEYSTORE_PROPERTIES);
		properties.put(KEYSTORE_PROPERTIES, getProperties());
		properties.put(WSHandlerConstants.PW_CALLBACK_REF, passwordCallback());
		properties.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
		return properties;
	}
{code}

DEBUG log file:
!log.txt!


was (Author: ondrusekj):
We use in out interceptors + Spring to configure CXF:

web.xml
{code:xml}
<servlet>
	<servlet-name>cxf</servlet-name>
	<servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
	<load-on-startup>1</load-on-startup>
</servlet>
{code}

cxf-servlet.xml
{code:xml}
<jaxws:endpoint id="cxfCarrierBillingEndpoint" address="/billing/" implementor="#carrierBillingEndpoint">
	<jaxws:outInterceptors>
		<ref bean="outgoingSecurityInterceptor"/>
	</jaxws:outInterceptors>
	<jaxws:inInterceptors>
		<ref bean="cryptoCoverageChecker"/>
		<ref bean="incomingSecurityInterceptor"/>
	</jaxws:inInterceptors>
</jaxws:endpoint>
{code}

Spring JavaConfig:
{code:java}
	public static final String KEYSTORE_SERVICE_NAME = "org.apache.ws.security.crypto.merlin.keystore.alias";
	public static final String KEYSTORE_SERVICE_PASSWORD = "keystore.service.password";
	public static final String KEYSTORE_PROPERTIES = "keystoreProperties";

	private static final CoverageType TYPE_SIGNED = CryptoCoverageUtil.CoverageType.SIGNED;
	private static final CoverageScope SCOOPED_ELEMENT = CryptoCoverageUtil.CoverageScope.ELEMENT;

	private static final String X_PATH_BODY_VERIFIER = "/soap:Envelope/soap:Body";
	private static final String X_PATH_TIMESTAMP_VERIFIER = "/soap:Envelope/soap:Header/wsse:Security/wsu:Timestamp";

	@Bean
	@Qualifier(KEYSTORE_PROPERTIES)
	public Properties getProperties() {
		return PropertiesLoaderUtils.loadProperties(...);
	}

	@Bean
	public Interceptor<SoapMessage> cryptoCoverageChecker() {
		Map<String, String> prefixes = Maps.newHashMap();
		prefixes.put("soap", "http://schemas.xmlsoap.org/soap/envelope/");
		prefixes.put("wsse", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd");
		prefixes.put("wsu", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd");

		List<XPathExpression> xPaths = Lists.newArrayList();
		xPaths.add(bodyVerifier());
		xPaths.add(timestampVerifier());

		return new CryptoCoverageChecker(prefixes, xPaths);
	}

	@Bean
	public CryptoCoverageChecker.XPathExpression bodyVerifier() {
		return new CryptoCoverageChecker.XPathExpression(X_PATH_BODY_VERIFIER, TYPE_SIGNED, SCOOPED_ELEMENT);
	}

	@Bean
	public CryptoCoverageChecker.XPathExpression timestampVerifier() {
		return new CryptoCoverageChecker.XPathExpression(X_PATH_TIMESTAMP_VERIFIER, TYPE_SIGNED, SCOOPED_ELEMENT);
	}

	@Bean
	public Interceptor<SoapMessage> incomingSecurityInterceptor() {
		Map<String, Object> properties = Maps.newHashMap();
		properties.putAll(getCommonWSSProperties());
		return new WSS4JInInterceptor(properties);
	}

	@Bean
	public Interceptor<SoapMessage> outgoingSecurityInterceptor() {
		Map<String, Object> properties = Maps.newHashMap();
		properties.put(WSHandlerConstants.USER, getKeystoreProperty(KEYSTORE_SERVICE_NAME));
		properties.put(WSHandlerConstants.ENCRYPTION_USER, "useReqSigCert");
		properties.putAll(getCommonWSSProperties());
		properties.put(
				WSHandlerConstants.SIGNATURE_PARTS,
				"{Element}{http://schemas.xmlsoap.org/soap/envelope/}Body;{Element}{http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd}Timestamp");
		return new WSS4JOutInterceptor(properties);
	}

	@Bean
	public ServiceKeystorePasswordCallback passwordCallback() {
		Map<String, String> credentials = Maps.newHashMap();
		credentials.put(getKeystoreProperty(KEYSTORE_SERVICE_NAME), getKeystoreProperty(KEYSTORE_SERVICE_PASSWORD));
		CredentialsHolder credentialsHolder = new CredentialsHolder(credentials);
		return new ServiceKeystorePasswordCallback(credentialsHolder);
	}

	private String getKeystoreProperty(String key) {
		return getProperties().getProperty(key);
	}

	private Map<String, Object> getCommonWSSProperties() {
		Map<String, Object> properties = Maps.newHashMap();
		properties.put(WSHandlerConstants.ACTION, WSHandlerConstants.TIMESTAMP + " " + WSHandlerConstants.SIGNATURE);
		properties.put(WSHandlerConstants.SIG_PROP_REF_ID, KEYSTORE_PROPERTIES);
		properties.put(WSHandlerConstants.ENC_PROP_REF_ID, KEYSTORE_PROPERTIES);
		properties.put(KEYSTORE_PROPERTIES, getProperties());
		properties.put(WSHandlerConstants.PW_CALLBACK_REF, passwordCallback());
		properties.put(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION, "true");
		return properties;
	}
{code}

DEBUG log file:
!log.txt!

> WS-S after upgrade fails with org.apache.ws.security.WSSecurityException: The signature or decryption was invalid
> -----------------------------------------------------------------------------------------------------------------
>
>                 Key: CXF-5679
>                 URL: https://issues.apache.org/jira/browse/CXF-5679
>             Project: CXF
>          Issue Type: Bug
>          Components: WS-* Components
>    Affects Versions: 2.7.9, 2.7.10
>            Reporter: Ján Ondrušek
>            Assignee: Colm O hEigeartaigh
>              Labels: security
>         Attachments: log.txt
>
>
> After upgrading CXF from version 2.7.5 to 2.7.9 or higher, we experienced this issue. Worked well with 2.7.5 and earlier.
> Request (our business data stripped and replaced with dummy ns1):
> {code:xml}
> <soapenv:Envelope xmlns:ns1="http://example/soap"
> 	xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
> 	<soapenv:Header>
> 		<wsse:Security soapenv:mustUnderstand="1"
> 			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">
> 			<ds:Signature Id="SIG-33" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
> 				<ds:SignedInfo>
> 					<ds:CanonicalizationMethod
> 						Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
> 						<ec:InclusiveNamespaces PrefixList="ns1 soapenv"
> 							xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
> 					</ds:CanonicalizationMethod>
> 					<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1" />
> 					<ds:Reference URI="#id-22">
> 						<ds:Transforms>
> 							<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
> 								<ec:InclusiveNamespaces PrefixList="ns1"
> 									xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
> 							</ds:Transform>
> 						</ds:Transforms>
> 						<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
> 						<ds:DigestValue>VF0g31FSsHWpdMN7lGVgQA1li4c=</ds:DigestValue>
> 					</ds:Reference>
> 					<ds:Reference URI="#TS-32">
> 						<ds:Transforms>
> 							<ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
> 								<ec:InclusiveNamespaces PrefixList="wsse ns1 soapenv"
> 									xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" />
> 							</ds:Transform>
> 						</ds:Transforms>
> 						<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />
> 						<ds:DigestValue>4yW2ssYnI+QB40HBdWexy80+GNo=</ds:DigestValue>
> 					</ds:Reference>
> 				</ds:SignedInfo>
> 				<ds:SignatureValue>QGIDsbR//zUyjUD36LtkiMJsIiT1vYionG8Y0blqif2QKrMB2AHnr9KXiYy7MbcdMaTVxn6gmKGN
> 					7bRjE6MX1VVf9ZPem5SfasHYQ6wS7l/I1NGUyGw227cv1AceDPje05Wjk5vmN9G1dKvbfECJhBLA
> 					7/OBAxJI+TYmYe94cu8=</ds:SignatureValue>
> 				<ds:KeyInfo Id="KI-6788C4A756C88F8773139703929455550">
> 					<wsse:SecurityTokenReference
> 						wsu:Id="STR-6788C4A756C88F8773139703929455551">
> 						<ds:X509Data>
> 							<ds:X509IssuerSerial>
> 								<ds:X509IssuerName>CN=clientuser</ds:X509IssuerName>
> 								<ds:X509SerialNumber>1288174342</ds:X509SerialNumber>
> 							</ds:X509IssuerSerial>
> 						</ds:X509Data>
> 					</wsse:SecurityTokenReference>
> 				</ds:KeyInfo>
> 			</ds:Signature>
> 			<wsu:Timestamp wsu:Id="TS-32">
> 				<wsu:Created>2014-04-09T10:28:14.554Z</wsu:Created>
> 				<wsu:Expires>2014-04-09T10:33:14.554Z</wsu:Expires>
> 			</wsu:Timestamp>
> 		</wsse:Security>
> 	</soapenv:Header>
> 	<soapenv:Body wsu:Id="id-22"
> 		xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
> 		<ns1:hello></ns1:hello>
> 	</soapenv:Body>
> </soapenv:Envelope>
> {code}
> Response:
> {code:xml}
> <soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
> 	<soap:Body>
> 		<soap:Fault>
> 			<faultcode
> 				xmlns:ns1="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">ns1:FailedCheck</faultcode>
> 			<faultstring>The signature or decryption was invalid</faultstring>
> 		</soap:Fault>
> 	</soap:Body>
> </soap:Envelope>
> {code}
> Log:
> {noformat}
> o.a.c.w.s.wss4j.WSS4JInInterceptor - org.apache.ws.security.WSSecurityException: The signature or decryption was invalid
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.ws.security.processor.SignatureProcessor.handleToken(SignatureProcessor.java:19
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.ws.security.WSSecurityEngine.processSecurityHeader(WSSecurityEngine.java:396)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.ws.security.wss4j.WSS4JInInterceptor.handleMessage(WSS4JInInterceptor.java:
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:272)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:12
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.jav
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:222)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:153)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:167)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.jav
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doPost(AbstractHTTPServlet.java:206)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:262)
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.ja
> o.a.c.w.s.wss4j.WSS4JInInterceptor - #011at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
> {noformat}



--
This message was sent by Atlassian JIRA
(v6.2#6252)