View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.test;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.InputStream;
24  import java.nio.charset.StandardCharsets;
25  import java.util.ArrayList;
26  import java.util.List;
27  import java.util.Properties;
28  
29  import javax.xml.crypto.dsig.SignatureMethod;
30  import javax.xml.stream.XMLStreamReader;
31  import javax.xml.stream.XMLStreamWriter;
32  import javax.xml.transform.dom.DOMSource;
33  import javax.xml.transform.stream.StreamResult;
34  
35  import org.apache.wss4j.binding.wssc.AbstractSecurityContextTokenType;
36  import org.apache.wss4j.common.bsp.BSPRule;
37  import org.apache.wss4j.common.crypto.Crypto;
38  import org.apache.wss4j.common.crypto.CryptoFactory;
39  import org.apache.wss4j.common.derivedKey.ConversationConstants;
40  import org.apache.wss4j.common.ext.WSSecurityException;
41  import org.apache.wss4j.common.util.SOAPUtil;
42  import org.apache.wss4j.dom.WSConstants;
43  import org.apache.wss4j.dom.engine.WSSConfig;
44  import org.apache.wss4j.dom.handler.WSHandlerConstants;
45  import org.apache.wss4j.dom.message.WSSecDKEncrypt;
46  import org.apache.wss4j.dom.message.WSSecDKSign;
47  import org.apache.wss4j.dom.message.WSSecHeader;
48  import org.apache.wss4j.dom.message.WSSecSecurityContextToken;
49  import org.apache.wss4j.dom.message.WSSecSignature;
50  import org.apache.wss4j.stax.ext.WSSConstants;
51  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
52  import org.apache.wss4j.stax.securityEvent.EncryptedPartSecurityEvent;
53  import org.apache.wss4j.stax.securityEvent.OperationSecurityEvent;
54  import org.apache.wss4j.stax.securityEvent.SignedPartSecurityEvent;
55  import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
56  import org.apache.wss4j.stax.setup.InboundWSSec;
57  import org.apache.wss4j.stax.setup.OutboundWSSec;
58  import org.apache.wss4j.stax.setup.WSSec;
59  import org.apache.wss4j.stax.test.utils.SecretKeyCallbackHandler;
60  import org.apache.wss4j.stax.test.utils.StAX2DOM;
61  import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
62  import org.apache.wss4j.stax.validate.SecurityContextTokenValidator;
63  import org.apache.wss4j.stax.validate.SecurityContextTokenValidatorImpl;
64  import org.apache.wss4j.stax.validate.TokenContext;
65  import org.apache.xml.security.stax.ext.XMLSecurityConstants;
66  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
67  import org.apache.xml.security.stax.securityEvent.SignatureValueSecurityEvent;
68  import org.apache.xml.security.stax.securityToken.InboundSecurityToken;
69  import org.junit.jupiter.api.BeforeAll;
70  import org.junit.jupiter.params.ParameterizedTest;
71  import org.junit.jupiter.params.provider.ValueSource;
72  import org.w3c.dom.Document;
73  import org.w3c.dom.NodeList;
74  
75  import static org.junit.jupiter.api.Assertions.assertEquals;
76  import static org.junit.jupiter.api.Assertions.assertTrue;
77  
78  public class SecurityContextTokenTest extends AbstractTestBase {
79  
80      @BeforeAll
81      public static void setUp() throws Exception {
82          WSSConfig.init();
83      }
84  
85      @ParameterizedTest
86      @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
87      public void testSCTDKTEncryptOutbound(int version) throws Exception {
88          byte[] secret = WSSConstants.generateBytes(128 / 8);
89  
90          ByteArrayOutputStream baos = new ByteArrayOutputStream();
91          {
92              WSSSecurityProperties securityProperties = new WSSSecurityProperties();
93              List<WSSConstants.Action> actions = new ArrayList<>();
94              actions.add(WSSConstants.ENCRYPTION_WITH_DERIVED_KEY);
95              securityProperties.setActions(actions);
96              CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(secret);
97              securityProperties.setCallbackHandler(callbackHandler);
98              securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
99              securityProperties.setEncryptionUser("receiver");
100             securityProperties.setEncryptionSymAlgorithm("http://www.w3.org/2001/04/xmlenc#aes128-cbc");
101             securityProperties.setDerivedKeyTokenReference(WSSConstants.DerivedKeyTokenReference.SecurityContextToken);
102 
103             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
104             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
105             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
106             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
107             xmlStreamWriter.close();
108 
109             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
110             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
111             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SOAP11_BODY.getLocalPart());
112             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSC0512_SCT.getNamespaceURI(), WSSConstants.TAG_WSC0512_SCT.getLocalPart());
113             assertEquals(nodeList.getLength(), 1);
114             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSC0512_DKT.getNamespaceURI(), WSSConstants.TAG_WSC0512_DKT.getLocalPart());
115             assertEquals(nodeList.getLength(), 1);
116             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_ReferenceList.getNamespaceURI(), WSSConstants.TAG_xenc_ReferenceList.getLocalPart());
117             assertEquals(nodeList.getLength(), 1);
118             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedKey.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedKey.getLocalPart());
119             assertEquals(nodeList.getLength(), 0);
120         }
121         {
122             String action = WSHandlerConstants.ENCRYPTION;
123             Properties properties = new Properties();
124             WSS4JCallbackHandlerImpl callbackHandler = new WSS4JCallbackHandlerImpl(secret);
125             properties.put(WSHandlerConstants.PW_CALLBACK_REF, callbackHandler);
126             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
127         }
128     }
129 
130     @ParameterizedTest
131     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
132     public void testSCTDKTEncryptInbound(int version) throws Exception {
133 
134         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
135         ByteArrayOutputStream baos = new ByteArrayOutputStream();
136         {
137             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
138             WSSecHeader secHeader = new WSSecHeader(doc);
139             secHeader.insertSecurityHeader();
140 
141             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
142             sctBuilder.setWscVersion(version);
143             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
144             sctBuilder.prepare(crypto);
145 
146             // Store the secret
147             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
148             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
149 
150             String tokenId = sctBuilder.getSctId();
151 
152             // Derived key encryption
153             WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
154             encrBuilder.setWscVersion(version);
155             encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
156             encrBuilder.setTokenIdentifier(tokenId);
157             encrBuilder.build(tempSecret);
158 
159             sctBuilder.prependSCTElementToHeader();
160 
161             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
162             transformer.transform(new DOMSource(doc), new StreamResult(baos));
163         }
164 
165         {
166             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
167             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
168             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
169             securityProperties.setCallbackHandler(callbackHandler);
170             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
171 
172             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
173                     WSSecurityEventConstants.AlgorithmSuite,
174                     WSSecurityEventConstants.AlgorithmSuite,
175                     WSSecurityEventConstants.AlgorithmSuite,
176                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
177                     WSSecurityEventConstants.ENCRYPTED_PART,
178                     WSSecurityEventConstants.OPERATION,
179             };
180             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
181 
182             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
183 
184             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
185 
186             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
187             assertEquals(nodeList.getLength(), 0);
188 
189             securityEventListener.compare();
190 
191             EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
192             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
193             String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
194             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
195 
196             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
197             List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
198 
199             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
200             for (SecurityEvent securityEvent : securityEvents) {
201                 if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
202                     encryptedPartSecurityEvents.add(securityEvent);
203                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
204                     operationSecurityEvents.add(securityEvent);
205                 }
206             }
207 
208             assertEquals(5, encryptedPartSecurityEvents.size());
209             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
210                     operationSecurityEvents.size() +
211                             encryptedPartSecurityEvents.size()
212             );
213         }
214     }
215 
216     @ParameterizedTest
217     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
218     public void testSCTDKTEncryptInboundAction(int version) throws Exception {
219 
220         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
221         ByteArrayOutputStream baos = new ByteArrayOutputStream();
222         {
223             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
224             String action = WSHandlerConstants.ENCRYPTION_DERIVED;
225 
226             Properties properties = new Properties();
227             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
228             properties.put(WSHandlerConstants.PW_CALLBACK_REF,  callbackHandler);
229             properties.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "SecurityContextToken");
230             if (version == ConversationConstants.VERSION_05_02) {
231                 properties.put(WSHandlerConstants.USE_2005_12_NAMESPACE, "false");
232             }
233             properties.put(WSHandlerConstants.USER, "receiver");
234             properties.put(WSHandlerConstants.ENC_SYM_ALGO,
235                            "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
236             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
237 
238             //some test that we can really sure we get what we want from WSS4J
239             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
240             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SOAP11_BODY.getLocalPart());
241 
242             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
243             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
244         }
245 
246         {
247             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
248             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
249             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
250             securityProperties.setCallbackHandler(callbackHandler);
251             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
252 
253             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
254                     WSSecurityEventConstants.AlgorithmSuite,
255                     WSSecurityEventConstants.AlgorithmSuite,
256                     WSSecurityEventConstants.AlgorithmSuite,
257                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
258                     WSSecurityEventConstants.ENCRYPTED_PART,
259                     WSSecurityEventConstants.OPERATION,
260             };
261             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
262 
263             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
264 
265             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
266 
267             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
268             assertEquals(nodeList.getLength(), 0);
269 
270             securityEventListener.compare();
271 
272             EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
273             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
274             String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
275             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
276 
277             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
278             List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
279 
280             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
281             for (SecurityEvent securityEvent : securityEvents) {
282                 if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
283                     encryptedPartSecurityEvents.add(securityEvent);
284                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
285                     operationSecurityEvents.add(securityEvent);
286                 }
287             }
288 
289             assertEquals(5, encryptedPartSecurityEvents.size());
290             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
291                     operationSecurityEvents.size() +
292                             encryptedPartSecurityEvents.size()
293             );
294         }
295     }
296 
297     @ParameterizedTest
298     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
299     public void testSCTKDKTSignOutbound(int version) throws Exception {
300         byte[] secret = WSSConstants.generateBytes(128 / 8);
301 
302         ByteArrayOutputStream baos = new ByteArrayOutputStream();
303         {
304             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
305             List<WSSConstants.Action> actions = new ArrayList<>();
306             actions.add(WSSConstants.SIGNATURE_WITH_DERIVED_KEY);
307             securityProperties.setActions(actions);
308             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(secret);
309             securityProperties.setCallbackHandler(callbackHandler);
310             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
311             securityProperties.setSignatureUser("transmitter");
312             securityProperties.setDerivedKeyTokenReference(WSSConstants.DerivedKeyTokenReference.SecurityContextToken);
313 
314             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
315             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
316             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
317             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
318             xmlStreamWriter.close();
319 
320             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
321             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
322             assertEquals(nodeList.getLength(), 1);
323             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSC0512_SCT.getNamespaceURI(), WSSConstants.TAG_WSC0512_SCT.getLocalPart());
324             assertEquals(nodeList.getLength(), 1);
325             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSC0512_DKT.getNamespaceURI(), WSSConstants.TAG_WSC0512_DKT.getLocalPart());
326             assertEquals(nodeList.getLength(), 1);
327             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_ReferenceList.getNamespaceURI(), WSSConstants.TAG_xenc_ReferenceList.getLocalPart());
328             assertEquals(nodeList.getLength(), 0);
329             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedKey.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedKey.getLocalPart());
330             assertEquals(nodeList.getLength(), 0);
331         }
332         {
333             String action = WSHandlerConstants.SIGNATURE;
334             Properties properties = new Properties();
335             WSS4JCallbackHandlerImpl callbackHandler = new WSS4JCallbackHandlerImpl(secret);
336             properties.put(WSHandlerConstants.PW_CALLBACK_REF, callbackHandler);
337             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
338         }
339     }
340 
341     @ParameterizedTest
342     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
343     public void testSCTKDKTSignInbound(int version) throws Exception {
344 
345         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
346         ByteArrayOutputStream baos = new ByteArrayOutputStream();
347         {
348             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
349             WSSecHeader secHeader = new WSSecHeader(doc);
350             secHeader.insertSecurityHeader();
351 
352             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
353             sctBuilder.setWscVersion(version);
354             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
355             sctBuilder.prepare(crypto);
356 
357             // Store the secret
358             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
359             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
360 
361             String tokenId = sctBuilder.getSctId();
362 
363             // Derived key signature
364             WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
365             sigBuilder.setWscVersion(version);
366             sigBuilder.setTokenIdentifier(tokenId);
367             sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
368             sigBuilder.build(tempSecret);
369 
370             sctBuilder.prependSCTElementToHeader();
371 
372             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
373             transformer.transform(new DOMSource(doc), new StreamResult(baos));
374         }
375 
376         {
377             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
378             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
379             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
380             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
381             securityProperties.setCallbackHandler(callbackHandler);
382             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
383 
384             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
385                     WSSecurityEventConstants.AlgorithmSuite,
386                     WSSecurityEventConstants.AlgorithmSuite,
387                     WSSecurityEventConstants.AlgorithmSuite,
388                     WSSecurityEventConstants.AlgorithmSuite,
389                     WSSecurityEventConstants.AlgorithmSuite,
390                     WSSecurityEventConstants.AlgorithmSuite,
391                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
392                     WSSecurityEventConstants.SignatureValue,
393                     WSSecurityEventConstants.SIGNED_PART,
394                     WSSecurityEventConstants.OPERATION,
395             };
396             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
397 
398             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
399 
400             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
401 
402             securityEventListener.compare();
403 
404             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
405             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
406             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
407             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
408             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
409             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
410 
411             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
412             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
413             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
414 
415             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
416             for (SecurityEvent securityEvent : securityEvents) {
417                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
418                     signedElementSecurityEvents.add(securityEvent);
419                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
420                     signatureValueSecurityEvents.add(securityEvent);
421                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
422                     operationSecurityEvents.add(securityEvent);
423                 }
424             }
425 
426             assertEquals(3, signedElementSecurityEvents.size());
427             assertEquals(6, signatureValueSecurityEvents.size());
428             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
429                     operationSecurityEvents.size() +
430                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size()
431             );
432         }
433     }
434 
435     @ParameterizedTest
436     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
437     public void testSCTKDKTSignInboundAction(int version) throws Exception {
438 
439         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
440         ByteArrayOutputStream baos = new ByteArrayOutputStream();
441         {
442             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
443             String action = WSHandlerConstants.SIGNATURE_DERIVED;
444 
445             Properties properties = new Properties();
446             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
447             properties.put(WSHandlerConstants.PW_CALLBACK_REF,  callbackHandler);
448             properties.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "SecurityContextToken");
449             if (version == ConversationConstants.VERSION_05_02) {
450                 properties.put(WSHandlerConstants.USE_2005_12_NAMESPACE, "false");
451             }
452             properties.put(WSHandlerConstants.USER, "transmitter");
453             properties.put(WSHandlerConstants.ENC_SYM_ALGO,
454                            "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
455             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
456 
457             //some test that we can really sure we get what we want from WSS4J
458             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
459             assertEquals(nodeList.getLength(), 1);
460 
461             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
462             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
463         }
464 
465         {
466             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
467             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
468             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
469             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
470             securityProperties.setCallbackHandler(callbackHandler);
471             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
472 
473             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
474                     WSSecurityEventConstants.AlgorithmSuite,
475                     WSSecurityEventConstants.AlgorithmSuite,
476                     WSSecurityEventConstants.AlgorithmSuite,
477                     WSSecurityEventConstants.AlgorithmSuite,
478                     WSSecurityEventConstants.AlgorithmSuite,
479                     WSSecurityEventConstants.AlgorithmSuite,
480                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
481                     WSSecurityEventConstants.SignatureValue,
482                     WSSecurityEventConstants.SIGNED_PART,
483                     WSSecurityEventConstants.OPERATION,
484             };
485             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
486 
487             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
488 
489             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
490 
491             securityEventListener.compare();
492 
493             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
494             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
495             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
496             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
497             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
498             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
499 
500             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
501             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
502             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
503 
504             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
505             for (SecurityEvent securityEvent : securityEvents) {
506                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
507                     signedElementSecurityEvents.add(securityEvent);
508                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
509                     signatureValueSecurityEvents.add(securityEvent);
510                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
511                     operationSecurityEvents.add(securityEvent);
512                 }
513             }
514 
515             assertEquals(3, signedElementSecurityEvents.size());
516             assertEquals(6, signatureValueSecurityEvents.size());
517             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
518                     operationSecurityEvents.size() +
519                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size()
520             );
521         }
522     }
523 
524     @ParameterizedTest
525     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
526     public void testSCTKDKTSignAbsoluteInbound(int version) throws Exception {
527 
528         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
529         ByteArrayOutputStream baos = new ByteArrayOutputStream();
530         {
531             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
532             WSSecHeader secHeader = new WSSecHeader(doc);
533             secHeader.insertSecurityHeader();
534 
535             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
536             sctBuilder.setWscVersion(version);
537             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
538             sctBuilder.prepare(crypto);
539 
540             // Store the secret
541             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
542             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
543 
544             // Derived key signature
545             WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
546             sigBuilder.setWscVersion(version);
547             sigBuilder.setTokenIdDirectId(true);
548             sigBuilder.setTokenIdentifier(sctBuilder.getIdentifier());
549             sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
550             sigBuilder.build(tempSecret);
551 
552             sctBuilder.prependSCTElementToHeader();
553 
554             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
555             transformer.transform(new DOMSource(doc), new StreamResult(baos));
556         }
557 
558         {
559             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
560             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
561             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
562             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
563             securityProperties.setCallbackHandler(callbackHandler);
564             securityProperties.addIgnoreBSPRule(BSPRule.R5204);
565             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
566             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
567 
568             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
569         }
570     }
571 
572     @ParameterizedTest
573     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
574     public void testSCTKDKTSignEncrypt(int version) throws Exception {
575 
576         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
577         ByteArrayOutputStream baos = new ByteArrayOutputStream();
578         {
579             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
580             WSSecHeader secHeader = new WSSecHeader(doc);
581             secHeader.insertSecurityHeader();
582 
583             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
584             sctBuilder.setWscVersion(version);
585             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
586             sctBuilder.prepare(crypto);
587 
588             // Store the secret
589             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
590             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
591 
592             String tokenId = sctBuilder.getSctId();
593 
594             // Derived key signature
595             WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
596             sigBuilder.setWscVersion(version);
597             if (version == ConversationConstants.VERSION_05_12) {
598                 sigBuilder.setCustomValueType(WSConstants.WSC_SCT_05_12);
599             } else {
600                 sigBuilder.setCustomValueType(WSConstants.WSC_SCT);
601             }
602             sigBuilder.setTokenIdentifier(tokenId);
603             sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
604             sigBuilder.build(tempSecret);
605 
606             // Derived key encryption
607             WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
608             encrBuilder.setWscVersion(version);
609             if (version == ConversationConstants.VERSION_05_12) {
610                 encrBuilder.setCustomValueType(WSConstants.WSC_SCT_05_12);
611             } else {
612                 encrBuilder.setCustomValueType(WSConstants.WSC_SCT);
613             }
614             encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
615             encrBuilder.setTokenIdentifier(tokenId);
616             encrBuilder.build(tempSecret);
617 
618             sctBuilder.prependSCTElementToHeader();
619 
620             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
621             transformer.transform(new DOMSource(doc), new StreamResult(baos));
622         }
623 
624         {
625             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
626             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
627             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
628             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
629             securityProperties.setCallbackHandler(callbackHandler);
630             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
631 
632             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
633                     WSSecurityEventConstants.AlgorithmSuite,
634                     WSSecurityEventConstants.AlgorithmSuite,
635                     WSSecurityEventConstants.AlgorithmSuite,
636                     WSSecurityEventConstants.AlgorithmSuite,
637                     WSSecurityEventConstants.AlgorithmSuite,
638                     WSSecurityEventConstants.AlgorithmSuite,
639                     WSSecurityEventConstants.AlgorithmSuite,
640                     WSSecurityEventConstants.AlgorithmSuite,
641                     WSSecurityEventConstants.AlgorithmSuite,
642                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
643                     WSSecurityEventConstants.SignatureValue,
644                     WSSecurityEventConstants.SIGNED_PART,
645                     WSSecurityEventConstants.ENCRYPTED_PART,
646                     WSSecurityEventConstants.OPERATION,
647             };
648             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
649 
650             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
651 
652             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
653 
654             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
655             assertEquals(nodeList.getLength(), 0);
656 
657             securityEventListener.compare();
658 
659             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
660             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
661             EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
662             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
663             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
664             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
665             String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
666             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
667 
668             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
669             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
670             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
671             List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
672 
673             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
674             for (SecurityEvent securityEvent : securityEvents) {
675                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
676                     signedElementSecurityEvents.add(securityEvent);
677                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
678                     signatureValueSecurityEvents.add(securityEvent);
679                 } else if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
680                     encryptedPartSecurityEvents.add(securityEvent);
681                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
682                     operationSecurityEvents.add(securityEvent);
683                 }
684             }
685 
686             assertEquals(3, signedElementSecurityEvents.size());
687             assertEquals(5, signatureValueSecurityEvents.size());
688             assertEquals(5, encryptedPartSecurityEvents.size());
689             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
690                     operationSecurityEvents.size() +
691                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size() + encryptedPartSecurityEvents.size()
692             );
693         }
694     }
695 
696     @ParameterizedTest
697     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
698     public void testSCTKDKTSignEncryptAction(int version) throws Exception {
699 
700         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
701         ByteArrayOutputStream baos = new ByteArrayOutputStream();
702         {
703             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
704             String action =
705                 WSHandlerConstants.SIGNATURE_DERIVED + " " + WSHandlerConstants.ENCRYPTION_DERIVED;
706 
707             Properties properties = new Properties();
708             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
709             properties.put(WSHandlerConstants.PW_CALLBACK_REF,  callbackHandler);
710             properties.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "SecurityContextToken");
711             if (version == ConversationConstants.VERSION_05_02) {
712                 properties.put(WSHandlerConstants.USE_2005_12_NAMESPACE, "false");
713             }
714             properties.put(WSHandlerConstants.USER, "transmitter");
715             properties.put(WSHandlerConstants.ENC_SYM_ALGO,
716                            "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
717             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
718 
719             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
720             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
721         }
722 
723         {
724             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
725             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
726             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
727             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
728             securityProperties.setCallbackHandler(callbackHandler);
729             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
730 
731             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
732                     WSSecurityEventConstants.AlgorithmSuite,
733                     WSSecurityEventConstants.AlgorithmSuite,
734                     WSSecurityEventConstants.AlgorithmSuite,
735                     WSSecurityEventConstants.AlgorithmSuite,
736                     WSSecurityEventConstants.AlgorithmSuite,
737                     WSSecurityEventConstants.AlgorithmSuite,
738                     WSSecurityEventConstants.AlgorithmSuite,
739                     WSSecurityEventConstants.AlgorithmSuite,
740                     WSSecurityEventConstants.AlgorithmSuite,
741                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
742                     WSSecurityEventConstants.SignatureValue,
743                     WSSecurityEventConstants.SIGNED_PART,
744                     WSSecurityEventConstants.ENCRYPTED_PART,
745                     WSSecurityEventConstants.OPERATION,
746             };
747             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
748 
749             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
750             XMLStreamReader secureXmlStreamReader = wsSecIn.processInMessage(xmlStreamReader, null, securityEventListener);
751 
752             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), secureXmlStreamReader);
753 
754             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
755             assertEquals(nodeList.getLength(), 0);
756 
757             securityEventListener.compare();
758 
759             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
760             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
761             EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
762             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
763             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
764             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
765             String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
766             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
767 
768             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
769             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
770             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
771             List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
772 
773             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
774             for (SecurityEvent securityEvent : securityEvents) {
775                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
776                     signedElementSecurityEvents.add(securityEvent);
777                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
778                     signatureValueSecurityEvents.add(securityEvent);
779                 } else if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
780                     encryptedPartSecurityEvents.add(securityEvent);
781                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
782                     operationSecurityEvents.add(securityEvent);
783                 }
784             }
785 
786             assertEquals(3, signedElementSecurityEvents.size());
787             assertEquals(5, signatureValueSecurityEvents.size());
788             assertEquals(5, encryptedPartSecurityEvents.size());
789             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
790                     operationSecurityEvents.size() +
791                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size() + encryptedPartSecurityEvents.size()
792             );
793         }
794     }
795 
796     @ParameterizedTest
797     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
798     public void testSCTKDKTEncryptSign(int version) throws Exception {
799 
800         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
801         ByteArrayOutputStream baos = new ByteArrayOutputStream();
802         {
803             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
804             WSSecHeader secHeader = new WSSecHeader(doc);
805             secHeader.insertSecurityHeader();
806 
807             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
808             sctBuilder.setWscVersion(version);
809             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
810             sctBuilder.prepare(crypto);
811 
812             // Store the secret
813             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
814             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
815 
816             String tokenId = sctBuilder.getSctId();
817 
818             // Derived key encryption
819             WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
820             encrBuilder.setWscVersion(version);
821             if (version == ConversationConstants.VERSION_05_12) {
822                 encrBuilder.setCustomValueType(WSConstants.WSC_SCT_05_12);
823             } else {
824                 encrBuilder.setCustomValueType(WSConstants.WSC_SCT);
825             }
826             encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
827             encrBuilder.setTokenIdentifier(tokenId);
828             encrBuilder.build(tempSecret);
829 
830             // Derived key signature
831             WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
832             sigBuilder.setWscVersion(version);
833             if (version == ConversationConstants.VERSION_05_12) {
834                 sigBuilder.setCustomValueType(WSConstants.WSC_SCT_05_12);
835             } else {
836                 sigBuilder.setCustomValueType(WSConstants.WSC_SCT);
837             }
838             sigBuilder.setTokenIdentifier(tokenId);
839             sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
840             sigBuilder.build(tempSecret);
841 
842             sctBuilder.prependSCTElementToHeader();
843 
844             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
845             transformer.transform(new DOMSource(doc), new StreamResult(baos));
846         }
847 
848         {
849             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
850             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
851             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
852             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
853             securityProperties.setCallbackHandler(callbackHandler);
854             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
855 
856             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
857                     WSSecurityEventConstants.AlgorithmSuite,
858                     WSSecurityEventConstants.AlgorithmSuite,
859                     WSSecurityEventConstants.AlgorithmSuite,
860                     WSSecurityEventConstants.AlgorithmSuite,
861                     WSSecurityEventConstants.AlgorithmSuite,
862                     WSSecurityEventConstants.AlgorithmSuite,
863                     WSSecurityEventConstants.AlgorithmSuite,
864                     WSSecurityEventConstants.AlgorithmSuite,
865                     WSSecurityEventConstants.AlgorithmSuite,
866                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
867                     WSSecurityEventConstants.SignatureValue,
868                     WSSecurityEventConstants.SIGNED_PART,
869                     WSSecurityEventConstants.ENCRYPTED_PART,
870                     WSSecurityEventConstants.OPERATION,
871             };
872             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
873 
874             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
875 
876             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
877 
878             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
879             assertEquals(nodeList.getLength(), 0);
880 
881             securityEventListener.compare();
882 
883             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
884             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
885             EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
886             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
887             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
888             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
889             String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
890             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
891 
892             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
893             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
894             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
895             List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
896 
897             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
898             for (SecurityEvent securityEvent : securityEvents) {
899                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
900                     signedElementSecurityEvents.add(securityEvent);
901                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
902                     signatureValueSecurityEvents.add(securityEvent);
903                 } else if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
904                     encryptedPartSecurityEvents.add(securityEvent);
905                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
906                     operationSecurityEvents.add(securityEvent);
907                 }
908             }
909 
910             assertEquals(3, signedElementSecurityEvents.size());
911             assertEquals(5, signatureValueSecurityEvents.size());
912             assertEquals(5, encryptedPartSecurityEvents.size());
913             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
914                     operationSecurityEvents.size() +
915                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size() + encryptedPartSecurityEvents.size()
916             );
917         }
918     }
919 
920     @ParameterizedTest
921     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
922     public void testSCTKDKTEncryptSignAction(int version) throws Exception {
923 
924         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
925         ByteArrayOutputStream baos = new ByteArrayOutputStream();
926         {
927             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
928             String action =
929                 WSHandlerConstants.ENCRYPTION_DERIVED + " " + WSHandlerConstants.SIGNATURE_DERIVED;
930 
931             Properties properties = new Properties();
932             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
933             properties.put(WSHandlerConstants.PW_CALLBACK_REF,  callbackHandler);
934             properties.put(WSHandlerConstants.DERIVED_TOKEN_REFERENCE, "SecurityContextToken");
935             if (version == ConversationConstants.VERSION_05_02) {
936                 properties.put(WSHandlerConstants.USE_2005_12_NAMESPACE, "false");
937             }
938             properties.put(WSHandlerConstants.USER, "transmitter");
939             properties.put(WSHandlerConstants.ENC_SYM_ALGO,
940                            "http://www.w3.org/2001/04/xmlenc#aes128-cbc");
941             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
942 
943             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
944             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
945         }
946 
947         {
948             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
949             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
950             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
951             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
952             securityProperties.setCallbackHandler(callbackHandler);
953             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
954 
955             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
956                     WSSecurityEventConstants.AlgorithmSuite,
957                     WSSecurityEventConstants.AlgorithmSuite,
958                     WSSecurityEventConstants.AlgorithmSuite,
959                     WSSecurityEventConstants.AlgorithmSuite,
960                     WSSecurityEventConstants.AlgorithmSuite,
961                     WSSecurityEventConstants.AlgorithmSuite,
962                     WSSecurityEventConstants.AlgorithmSuite,
963                     WSSecurityEventConstants.AlgorithmSuite,
964                     WSSecurityEventConstants.AlgorithmSuite,
965                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
966                     WSSecurityEventConstants.SignatureValue,
967                     WSSecurityEventConstants.SIGNED_PART,
968                     WSSecurityEventConstants.ENCRYPTED_PART,
969                     WSSecurityEventConstants.OPERATION,
970             };
971             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
972 
973             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
974 
975             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
976 
977             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
978             assertEquals(nodeList.getLength(), 0);
979 
980             securityEventListener.compare();
981 
982             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
983             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
984             EncryptedPartSecurityEvent encryptedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.ENCRYPTED_PART);
985             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
986             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
987             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
988             String encryptedPartCorrelationID = encryptedPartSecurityEvent.getCorrelationID();
989             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
990 
991             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
992             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
993             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
994             List<SecurityEvent> encryptedPartSecurityEvents = new ArrayList<>();
995 
996             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
997             for (SecurityEvent securityEvent : securityEvents) {
998                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
999                     signedElementSecurityEvents.add(securityEvent);
1000                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
1001                     signatureValueSecurityEvents.add(securityEvent);
1002                 } else if (securityEvent.getCorrelationID().equals(encryptedPartCorrelationID)) {
1003                     encryptedPartSecurityEvents.add(securityEvent);
1004                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
1005                     operationSecurityEvents.add(securityEvent);
1006                 }
1007             }
1008 
1009             assertEquals(3, signedElementSecurityEvents.size());
1010             assertEquals(5, signatureValueSecurityEvents.size());
1011             assertEquals(5, encryptedPartSecurityEvents.size());
1012             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
1013                     operationSecurityEvents.size() +
1014                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size() + encryptedPartSecurityEvents.size()
1015             );
1016         }
1017     }
1018 
1019 
1020     @ParameterizedTest
1021     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
1022     public void testSCTSign(int version) throws Exception {
1023 
1024         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
1025         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1026         {
1027             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
1028             WSSecHeader secHeader = new WSSecHeader(doc);
1029             secHeader.insertSecurityHeader();
1030 
1031             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
1032             sctBuilder.setWscVersion(version);
1033             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
1034             sctBuilder.prepare(crypto);
1035 
1036             // Store the secret
1037             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
1038             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
1039 
1040             String tokenId = sctBuilder.getSctId();
1041 
1042             WSSecSignature builder = new WSSecSignature(secHeader);
1043             builder.setSecretKey(tempSecret);
1044             builder.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
1045             builder.setCustomTokenValueType(WSConstants.WSC_SCT);
1046             builder.setCustomTokenId(tokenId);
1047             builder.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
1048             builder.build(crypto);
1049 
1050             sctBuilder.prependSCTElementToHeader();
1051 
1052             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
1053             transformer.transform(new DOMSource(doc), new StreamResult(baos));
1054         }
1055 
1056         {
1057             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1058             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1059             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
1060             securityProperties.setCallbackHandler(callbackHandler);
1061             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
1062 
1063             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
1064                     WSSecurityEventConstants.AlgorithmSuite,
1065                     WSSecurityEventConstants.AlgorithmSuite,
1066                     WSSecurityEventConstants.AlgorithmSuite,
1067                     WSSecurityEventConstants.AlgorithmSuite,
1068                     WSSecurityEventConstants.SECURITY_CONTEXT_TOKEN,
1069                     WSSecurityEventConstants.SignatureValue,
1070                     WSSecurityEventConstants.SIGNED_PART,
1071                     WSSecurityEventConstants.OPERATION,
1072             };
1073             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
1074 
1075             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
1076             XMLStreamReader secureXmlStreamReader = wsSecIn.processInMessage(xmlStreamReader, null, securityEventListener);
1077 
1078             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), secureXmlStreamReader);
1079 
1080             securityEventListener.compare();
1081 
1082             SignedPartSecurityEvent signedPartSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SIGNED_PART);
1083             SignatureValueSecurityEvent signatureValueSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.SignatureValue);
1084             OperationSecurityEvent operationSecurityEvent = securityEventListener.getSecurityEvent(WSSecurityEventConstants.OPERATION);
1085             String signedElementCorrelationID = signedPartSecurityEvent.getCorrelationID();
1086             String signatureValueCorrelationID = signatureValueSecurityEvent.getCorrelationID();
1087             String operationCorrelationID = operationSecurityEvent.getCorrelationID();
1088 
1089             List<SecurityEvent> operationSecurityEvents = new ArrayList<>();
1090             List<SecurityEvent> signedElementSecurityEvents = new ArrayList<>();
1091             List<SecurityEvent> signatureValueSecurityEvents = new ArrayList<>();
1092 
1093             List<SecurityEvent> securityEvents = securityEventListener.getReceivedSecurityEvents();
1094             for (SecurityEvent securityEvent : securityEvents) {
1095                 if (securityEvent.getCorrelationID().equals(signedElementCorrelationID)) {
1096                     signedElementSecurityEvents.add(securityEvent);
1097                 } else if (securityEvent.getCorrelationID().equals(signatureValueCorrelationID)) {
1098                     signatureValueSecurityEvents.add(securityEvent);
1099                 } else if (securityEvent.getCorrelationID().equals(operationCorrelationID)) {
1100                     operationSecurityEvents.add(securityEvent);
1101                 }
1102             }
1103 
1104             assertEquals(3, signedElementSecurityEvents.size());
1105             assertEquals(4, signatureValueSecurityEvents.size());
1106             assertEquals(securityEventListener.getReceivedSecurityEvents().size(),
1107                     operationSecurityEvents.size() +
1108                             signedElementSecurityEvents.size() + signatureValueSecurityEvents.size()
1109             );
1110         }
1111     }
1112 
1113     @ParameterizedTest
1114     @ValueSource(ints = {ConversationConstants.VERSION_05_02, ConversationConstants.VERSION_05_12})
1115     public void testSCTCustomValidator(int version) throws Exception {
1116         byte[] tempSecret = XMLSecurityConstants.generateBytes(16);
1117         ByteArrayOutputStream baos = new ByteArrayOutputStream();
1118         {
1119             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
1120             WSSecHeader secHeader = new WSSecHeader(doc);
1121             secHeader.insertSecurityHeader();
1122 
1123             WSSecSecurityContextToken sctBuilder = new WSSecSecurityContextToken(secHeader, null);
1124             sctBuilder.setWscVersion(version);
1125             Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
1126             sctBuilder.prepare(crypto);
1127 
1128             // Store the secret
1129             SecretKeyCallbackHandler callbackHandler = new SecretKeyCallbackHandler();
1130             callbackHandler.addSecretKey(sctBuilder.getIdentifier(), tempSecret);
1131 
1132             String tokenId = sctBuilder.getSctId();
1133 
1134             WSSecSignature builder = new WSSecSignature(secHeader);
1135             builder.setSecretKey(tempSecret);
1136             builder.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
1137             builder.setCustomTokenValueType(WSConstants.WSC_SCT);
1138             builder.setCustomTokenId(tokenId);
1139             builder.setSignatureAlgorithm(SignatureMethod.HMAC_SHA1);
1140             builder.build(crypto);
1141 
1142             sctBuilder.prependSCTElementToHeader();
1143 
1144             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
1145             transformer.transform(new DOMSource(doc), new StreamResult(baos));
1146         }
1147 
1148         {
1149             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
1150             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
1151             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl(tempSecret);
1152             securityProperties.setCallbackHandler(callbackHandler);
1153 
1154             final boolean[] validatorCalled = {false};
1155             SecurityContextTokenValidator validator = new SecurityContextTokenValidatorImpl() {
1156                 @Override
1157                 public InboundSecurityToken validate(AbstractSecurityContextTokenType securityContextTokenType, String identifier, TokenContext tokenContext) throws WSSecurityException {
1158                     validatorCalled[0] = true;
1159                     return super.validate(securityContextTokenType, identifier, tokenContext);
1160                 }
1161             };
1162 
1163             if (version == ConversationConstants.VERSION_05_02) {
1164                 securityProperties.addValidator(WSSConstants.TAG_WSC0502_SCT, validator);
1165             } else {
1166                 securityProperties.addValidator(WSSConstants.TAG_WSC0512_SCT, validator);
1167             }
1168 
1169             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
1170 
1171             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray()));
1172             XMLStreamReader secureXmlStreamReader = wsSecIn.processInMessage(xmlStreamReader);
1173 
1174             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), secureXmlStreamReader);
1175 
1176             assertTrue(validatorCalled[0], "Validator should be called when configured");
1177         }
1178     }
1179 }