1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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.security.Key;
26 import java.security.NoSuchAlgorithmException;
27 import java.util.ArrayList;
28 import java.util.List;
29
30 import javax.crypto.KeyGenerator;
31 import javax.crypto.SecretKey;
32 import javax.xml.namespace.QName;
33 import javax.xml.stream.XMLStreamReader;
34 import javax.xml.stream.XMLStreamWriter;
35 import javax.xml.transform.dom.DOMSource;
36 import javax.xml.transform.stream.StreamResult;
37
38 import org.apache.wss4j.common.WSEncryptionPart;
39 import org.apache.wss4j.common.crypto.Crypto;
40 import org.apache.wss4j.common.crypto.CryptoFactory;
41 import org.apache.wss4j.common.ext.WSSecurityException;
42 import org.apache.wss4j.common.util.KeyUtils;
43 import org.apache.wss4j.dom.WSConstants;
44 import org.apache.wss4j.dom.handler.WSHandlerConstants;
45 import org.apache.wss4j.dom.message.WSSecEncrypt;
46 import org.apache.wss4j.dom.message.WSSecHeader;
47 import org.apache.wss4j.dom.message.WSSecSignature;
48 import org.apache.wss4j.stax.ext.WSSConstants;
49 import org.apache.wss4j.stax.ext.WSSSecurityProperties;
50 import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
51 import org.apache.wss4j.stax.setup.OutboundWSSec;
52 import org.apache.wss4j.stax.setup.WSSec;
53 import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
54 import org.apache.xml.security.exceptions.XMLSecurityException;
55 import org.apache.xml.security.stax.config.JCEAlgorithmMapper;
56 import org.apache.xml.security.stax.ext.SecurePart;
57 import org.apache.xml.security.stax.impl.OutboundSecurityContextImpl;
58 import org.apache.xml.security.stax.impl.securityToken.GenericOutboundSecurityToken;
59 import org.apache.xml.security.stax.impl.util.IDGenerator;
60 import org.apache.xml.security.stax.securityEvent.SecurityEvent;
61 import org.apache.xml.security.stax.securityToken.OutboundSecurityToken;
62 import org.apache.xml.security.stax.securityToken.SecurityTokenProvider;
63 import org.junit.jupiter.api.Test;
64 import org.w3c.dom.Document;
65 import org.w3c.dom.Element;
66 import org.w3c.dom.NodeList;
67
68 import static org.junit.jupiter.api.Assertions.assertEquals;
69
70 public class SignatureEncryptionTest extends AbstractTestBase {
71
72 @Test
73 public void testSignatureEncryptionOutbound() throws Exception {
74
75 ByteArrayOutputStream baos;
76 {
77 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
78 List<WSSConstants.Action> actions = new ArrayList<>();
79 actions.add(WSSConstants.SIGNATURE);
80 actions.add(WSSConstants.ENCRYPTION);
81 actions.add(WSSConstants.TIMESTAMP);
82 securityProperties.setActions(actions);
83 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
84 securityProperties.setEncryptionUser("receiver");
85 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
86 securityProperties.setSignatureUser("transmitter");
87 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
88
89 securityProperties.addSignaturePart(
90 new SecurePart(new QName(WSSConstants.NS_WSU10, "Timestamp"), SecurePart.Modifier.Element)
91 );
92 securityProperties.addSignaturePart(
93 new SecurePart(new QName(WSSConstants.NS_SOAP11, "Body"), SecurePart.Modifier.Element)
94 );
95
96 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
97 baos = doOutboundSecurity(securityProperties, sourceDocument);
98
99 documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
100 }
101
102
103 {
104 String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.TIMESTAMP;
105 doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
106 }
107 }
108
109 @Test
110 public void testEncryptionSymmetricOutbound() throws Exception {
111
112 ByteArrayOutputStream baos;
113 {
114 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
115 List<WSSConstants.Action> actions = new ArrayList<>();
116 actions.add(WSSConstants.ENCRYPTION);
117 actions.add(WSSConstants.TIMESTAMP);
118 securityProperties.setActions(actions);
119 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
120 securityProperties.setEncryptionUser("receiver");
121
122 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
123
124
125 String keyAlgorithm =
126 JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(WSSConstants.NS_XENC_AES128);
127 KeyGenerator keyGen;
128 try {
129 keyGen = KeyGenerator.getInstance(keyAlgorithm);
130 } catch (NoSuchAlgorithmException e) {
131 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
132 }
133 int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(WSSConstants.NS_XENC_AES128);
134 keyGen.init(keyLength);
135
136 final Key symmetricKey = keyGen.generateKey();
137
138 final String ekId = IDGenerator.generateID(null);
139
140 final GenericOutboundSecurityToken encryptedKeySecurityToken =
141 new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
142
143 final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
144 new SecurityTokenProvider<OutboundSecurityToken>() {
145
146 @Override
147 public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
148 return encryptedKeySecurityToken;
149 }
150
151 @Override
152 public String getId() {
153 return ekId;
154 }
155 };
156
157 final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl();
158 outboundSecurityContext.putList(SecurityEvent.class, new ArrayList<SecurityEvent>());
159
160
161 outboundSecurityContext.registerSecurityTokenProvider(encryptedKeySecurityTokenProvider.getId(), encryptedKeySecurityTokenProvider);
162 outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, encryptedKeySecurityTokenProvider.getId());
163
164 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
165
166 baos = new ByteArrayOutputStream();
167 XMLStreamWriter xmlStreamWriter =
168 wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), outboundSecurityContext);
169 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
170 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
171 xmlStreamWriter.close();
172
173 documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
174 }
175
176
177 {
178 String action = WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.TIMESTAMP;
179 doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
180 }
181 }
182
183 @Test
184 public void testSignatureEncryptionSymmetricOutbound() throws Exception {
185
186 ByteArrayOutputStream baos;
187 {
188 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
189 List<WSSConstants.Action> actions = new ArrayList<>();
190 actions.add(WSSConstants.SIGNATURE);
191 actions.add(WSSConstants.ENCRYPTION);
192 actions.add(WSSConstants.TIMESTAMP);
193 securityProperties.setActions(actions);
194 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
195 securityProperties.setEncryptionUser("receiver");
196
197 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
198 securityProperties.setSignatureUser("transmitter");
199 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
200
201 securityProperties.setSignatureAlgorithm(WSSConstants.NS_XMLDSIG_HMACSHA1);
202 securityProperties.setSignatureKeyIdentifier(
203 WSSecurityTokenConstants.KeyIdentifier_EncryptedKey
204 );
205
206 securityProperties.addSignaturePart(
207 new SecurePart(new QName(WSSConstants.NS_WSU10, "Timestamp"), SecurePart.Modifier.Element)
208 );
209 securityProperties.addSignaturePart(
210 new SecurePart(new QName(WSSConstants.NS_SOAP11, "Body"), SecurePart.Modifier.Element)
211 );
212
213 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
214
215
216 String keyAlgorithm =
217 JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(WSSConstants.NS_XENC_AES128);
218 KeyGenerator keyGen;
219 try {
220 keyGen = KeyGenerator.getInstance(keyAlgorithm);
221 } catch (NoSuchAlgorithmException e) {
222 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
223 }
224 int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(WSSConstants.NS_XENC_AES128);
225 keyGen.init(keyLength);
226
227 final Key symmetricKey = keyGen.generateKey();
228
229 final String ekId = IDGenerator.generateID(null);
230
231 final GenericOutboundSecurityToken encryptedKeySecurityToken =
232 new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
233
234 final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
235 new SecurityTokenProvider<OutboundSecurityToken>() {
236
237 @Override
238 public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
239 return encryptedKeySecurityToken;
240 }
241
242 @Override
243 public String getId() {
244 return ekId;
245 }
246 };
247
248 final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl();
249 outboundSecurityContext.putList(SecurityEvent.class, new ArrayList<SecurityEvent>());
250
251
252 outboundSecurityContext.registerSecurityTokenProvider(encryptedKeySecurityTokenProvider.getId(), encryptedKeySecurityTokenProvider);
253 outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, encryptedKeySecurityTokenProvider.getId());
254 outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, encryptedKeySecurityTokenProvider.getId());
255
256 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
257
258 baos = new ByteArrayOutputStream();
259 XMLStreamWriter xmlStreamWriter =
260 wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), outboundSecurityContext);
261 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
262 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
263 xmlStreamWriter.close();
264
265 Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
266
267 NodeList securityHeaderElement = document.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
268 assertEquals(1, securityHeaderElement.getLength());
269 NodeList childs = securityHeaderElement.item(0).getChildNodes();
270
271 assertEquals(childs.getLength(), 4);
272 assertEquals(childs.item(0).getLocalName(), "Timestamp");
273 assertEquals(childs.item(1).getLocalName(), "EncryptedKey");
274 assertEquals(childs.item(2).getLocalName(), "ReferenceList");
275 assertEquals(childs.item(3).getLocalName(), "Signature");
276 }
277
278
279 {
280 String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.TIMESTAMP;
281 doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
282 }
283 }
284
285 @Test
286 public void testEncryptionSignatureSymmetricOutbound() throws Exception {
287
288 ByteArrayOutputStream baos;
289 {
290 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
291 List<WSSConstants.Action> actions = new ArrayList<>();
292 actions.add(WSSConstants.ENCRYPTION);
293 actions.add(WSSConstants.SIGNATURE);
294 actions.add(WSSConstants.TIMESTAMP);
295 securityProperties.setActions(actions);
296 securityProperties.loadEncryptionKeystore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
297 securityProperties.setEncryptionUser("receiver");
298
299 securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
300 securityProperties.setSignatureUser("transmitter");
301 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
302
303 securityProperties.setSignatureAlgorithm(WSSConstants.NS_XMLDSIG_HMACSHA1);
304 securityProperties.setSignatureKeyIdentifier(
305 WSSecurityTokenConstants.KeyIdentifier_EncryptedKey
306 );
307
308 securityProperties.addSignaturePart(
309 new SecurePart(new QName(WSSConstants.NS_WSU10, "Timestamp"), SecurePart.Modifier.Element)
310 );
311 securityProperties.addSignaturePart(
312 new SecurePart(new QName(WSSConstants.NS_SOAP11, "Body"), SecurePart.Modifier.Element)
313 );
314
315 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
316
317
318 String keyAlgorithm =
319 JCEAlgorithmMapper.getJCEKeyAlgorithmFromURI(WSSConstants.NS_XENC_AES128);
320 KeyGenerator keyGen;
321 try {
322 keyGen = KeyGenerator.getInstance(keyAlgorithm);
323 } catch (NoSuchAlgorithmException e) {
324 throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
325 }
326 int keyLength = JCEAlgorithmMapper.getKeyLengthFromURI(WSSConstants.NS_XENC_AES128);
327 keyGen.init(keyLength);
328
329 final Key symmetricKey = keyGen.generateKey();
330
331 final String ekId = IDGenerator.generateID(null);
332
333 final GenericOutboundSecurityToken encryptedKeySecurityToken =
334 new GenericOutboundSecurityToken(ekId, WSSecurityTokenConstants.EncryptedKeyToken, symmetricKey);
335
336 final SecurityTokenProvider<OutboundSecurityToken> encryptedKeySecurityTokenProvider =
337 new SecurityTokenProvider<OutboundSecurityToken>() {
338
339 @Override
340 public OutboundSecurityToken getSecurityToken() throws XMLSecurityException {
341 return encryptedKeySecurityToken;
342 }
343
344 @Override
345 public String getId() {
346 return ekId;
347 }
348 };
349
350 final OutboundSecurityContextImpl outboundSecurityContext = new OutboundSecurityContextImpl();
351 outboundSecurityContext.putList(SecurityEvent.class, new ArrayList<SecurityEvent>());
352
353
354 outboundSecurityContext.registerSecurityTokenProvider(encryptedKeySecurityTokenProvider.getId(), encryptedKeySecurityTokenProvider);
355 outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_ENCRYPTION, encryptedKeySecurityTokenProvider.getId());
356 outboundSecurityContext.put(WSSConstants.PROP_USE_THIS_TOKEN_ID_FOR_SIGNATURE, encryptedKeySecurityTokenProvider.getId());
357
358 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
359
360 baos = new ByteArrayOutputStream();
361 XMLStreamWriter xmlStreamWriter =
362 wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), outboundSecurityContext);
363 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
364 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
365 xmlStreamWriter.close();
366
367 Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
368
369 NodeList securityHeaderElement = document.getElementsByTagNameNS(WSConstants.WSSE_NS, "Security");
370 assertEquals(1, securityHeaderElement.getLength());
371 NodeList childs = securityHeaderElement.item(0).getChildNodes();
372
373 assertEquals(childs.getLength(), 4);
374 assertEquals(childs.item(0).getLocalName(), "Timestamp");
375 assertEquals(childs.item(1).getLocalName(), "EncryptedKey");
376 assertEquals(childs.item(2).getLocalName(), "Signature");
377 assertEquals(childs.item(3).getLocalName(), "ReferenceList");
378 }
379
380
381 {
382 String action = WSHandlerConstants.ENCRYPTION + " " + WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.TIMESTAMP;
383 doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
384 }
385 }
386
387 @Test
388 public void testEncryptedDataTokenSecurityHeaderWithoutReferenceInbound() throws Exception {
389 ByteArrayOutputStream baos = new ByteArrayOutputStream();
390 {
391 InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
392
393 Document doc = documentBuilderFactory.newDocumentBuilder().parse(sourceDocument);
394
395 WSSecHeader secHeader = new WSSecHeader(doc);
396 secHeader.insertSecurityHeader();
397
398 WSSecSignature sign = new WSSecSignature(secHeader);
399 sign.setUserInfo("transmitter", "default");
400 sign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
401
402 Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
403
404 sign.build( crypto);
405
406 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
407 builder.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
408 builder.setUserInfo("receiver");
409
410 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
411 SecretKey symmetricKey = keyGen.generateKey();
412 builder.prepare(crypto, symmetricKey);
413
414 WSEncryptionPart bst = new WSEncryptionPart("BinarySecurityToken", "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "Element");
415 WSEncryptionPart def = new WSEncryptionPart("definitions", "http://schemas.xmlsoap.org/wsdl/", "Element");
416 List<WSEncryptionPart> encryptionParts = new ArrayList<>();
417 encryptionParts.add(bst);
418 encryptionParts.add(def);
419 Element ref = builder.encryptForRef(null, encryptionParts, symmetricKey);
420 ref.removeChild(ref.getElementsByTagNameNS("http://www.w3.org/2001/04/xmlenc#", "DataReference").item(0));
421 builder.addExternalRefElement(ref);
422 builder.prependToHeader();
423
424 javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
425 transformer.transform(new DOMSource(doc), new StreamResult(baos));
426 }
427
428
429 {
430 WSSSecurityProperties securityProperties = new WSSSecurityProperties();
431 securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
432 securityProperties.setCallbackHandler(new CallbackHandlerImpl());
433 Document document = doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
434
435
436 NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_xenc_EncryptedData.getNamespaceURI(), WSSConstants.TAG_xenc_EncryptedData.getLocalPart());
437 assertEquals(nodeList.getLength(), 0);
438 }
439 }
440 }