1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.message;
21
22 import java.nio.charset.StandardCharsets;
23 import java.security.MessageDigest;
24 import java.util.Collections;
25
26 import javax.security.auth.callback.CallbackHandler;
27
28 import org.apache.wss4j.common.bsp.BSPRule;
29 import org.apache.wss4j.common.crypto.Crypto;
30 import org.apache.wss4j.common.crypto.CryptoFactory;
31 import org.apache.wss4j.common.ext.WSSecurityException;
32 import org.apache.wss4j.common.token.SecurityTokenReference;
33 import org.apache.wss4j.common.util.SOAPUtil;
34 import org.apache.wss4j.common.util.UsernameTokenUtil;
35 import org.apache.wss4j.common.util.XMLUtils;
36 import org.apache.wss4j.dom.WSConstants;
37 import org.apache.wss4j.dom.common.EncodedPasswordCallbackHandler;
38
39 import org.apache.wss4j.dom.common.UsernamePasswordCallbackHandler;
40 import org.apache.wss4j.dom.engine.WSSConfig;
41 import org.apache.wss4j.dom.engine.WSSecurityEngine;
42 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
43 import org.apache.wss4j.dom.handler.RequestData;
44 import org.apache.wss4j.dom.handler.WSHandlerResult;
45 import org.apache.wss4j.dom.message.token.UsernameToken;
46 import org.apache.wss4j.dom.util.WSSecurityUtil;
47
48 import org.junit.jupiter.api.Test;
49 import org.w3c.dom.Document;
50
51 import static org.junit.jupiter.api.Assertions.assertArrayEquals;
52 import static org.junit.jupiter.api.Assertions.assertFalse;
53 import static org.junit.jupiter.api.Assertions.assertTrue;
54 import static org.junit.jupiter.api.Assertions.fail;
55
56
57
58
59
60
61 public class UTDerivedKeyTest {
62 private static final org.slf4j.Logger LOG =
63 org.slf4j.LoggerFactory.getLogger(UTDerivedKeyTest.class);
64 private CallbackHandler callbackHandler = new UsernamePasswordCallbackHandler();
65 private Crypto crypto;
66
67 public UTDerivedKeyTest() throws Exception {
68 crypto = CryptoFactory.getInstance();
69 }
70
71
72
73
74 @Test
75 public void testUsernameTokenUnit() throws Exception {
76 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
77 WSSecHeader secHeader = new WSSecHeader(doc);
78 secHeader.insertSecurityHeader();
79
80 UsernameToken usernameToken = new UsernameToken(true, doc, null);
81 usernameToken.setName("bob");
82
83 byte[] salt = UsernameTokenUtil.generateSalt(false);
84 usernameToken.addSalt(doc, salt);
85 assertTrue(salt.length == 16);
86 assertTrue(salt[0] == 0x02);
87 byte[] utSalt = usernameToken.getSalt();
88 assertTrue(salt.length == utSalt.length);
89 for (int i = 0; i < salt.length; i++) {
90 assertTrue(salt[i] == utSalt[i]);
91 }
92
93 usernameToken.addIteration(doc, 500);
94 assertTrue(usernameToken.getIteration() == 500);
95
96 WSSecurityUtil.prependChildElement(
97 secHeader.getSecurityHeaderElement(), usernameToken.getElement()
98 );
99
100 String outputString =
101 XMLUtils.prettyDocumentToString(doc);
102 assertTrue(outputString.contains("wsse:Username"));
103 assertFalse(outputString.contains("wsse:Password"));
104 assertTrue(outputString.contains("wsse11:Salt"));
105 assertTrue(outputString.contains("wsse11:Iteration"));
106
107 byte[] derivedKey = UsernameTokenUtil.generateDerivedKey("security", salt, 500);
108 assertTrue(derivedKey.length == 20);
109
110
111 derivedKey = UsernameTokenUtil.generateDerivedKey(org.apache.xml.security.utils.XMLUtils.decode("c2VjdXJpdHk="),
112 salt, 500);
113 assertTrue(derivedKey.length == 20);
114 }
115
116
117
118
119 @Test
120 public void testDerivedKeyWithEncodedPasswordBaseline() throws Exception {
121 String password = "password";
122
123 byte[] passwordHash = MessageDigest.getInstance("SHA-1").digest(password.getBytes(StandardCharsets.UTF_8));
124
125 byte[] salt = org.apache.xml.security.utils.XMLUtils.decode("LKpycbfgRzwDnBz6kkhAAQ==");
126 int iteration = 1049;
127 byte[] expectedDerivedKey = org.apache.xml.security.utils.XMLUtils.decode("C7Ll/OY4TECb6hZuMMiX/5hzszo=");
128 byte[] derivedKey = UsernameTokenUtil.generateDerivedKey(passwordHash, salt, iteration);
129 assertArrayEquals(expectedDerivedKey, derivedKey, "the derived key is not as expected");
130 }
131
132
133
134
135 @Test
136 public void testDerivedKeyEncryption() throws Exception {
137 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
138 WSSecHeader secHeader = new WSSecHeader(doc);
139 secHeader.insertSecurityHeader();
140
141 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
142 builder.setUserInfo("bob", "security");
143 builder.addDerivedKey(1000);
144 byte[] salt = UsernameTokenUtil.generateSalt(false);
145 builder.prepare(salt);
146
147 byte[] derivedKey = builder.getDerivedKey(salt);
148 assertTrue(derivedKey.length == 20);
149
150 String tokenIdentifier = builder.getId();
151
152
153
154
155 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
156 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
157 encrBuilder.setTokenIdentifier(tokenIdentifier);
158 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
159 Document encryptedDoc = encrBuilder.build(derivedKey);
160
161 builder.prependToHeader();
162
163 String outputString =
164 XMLUtils.prettyDocumentToString(encryptedDoc);
165 assertTrue(outputString.contains("wsse:Username"));
166 assertFalse(outputString.contains("wsse:Password"));
167 assertTrue(outputString.contains("wsse11:Salt"));
168 assertTrue(outputString.contains("wsse11:Iteration"));
169 assertFalse(outputString.contains("testMethod"));
170 if (LOG.isDebugEnabled()) {
171 LOG.debug(outputString);
172 }
173
174 verify(encryptedDoc);
175
176 try {
177 verify(encryptedDoc, false);
178 fail("Failure expected on deriving keys from a UsernameToken not allowed");
179 } catch (WSSecurityException ex) {
180 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
181 }
182 }
183
184
185
186
187 @Test
188 public void testDerivedKeyEncryptionWithEncodedPassword() throws Exception {
189 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
190 WSSecHeader secHeader = new WSSecHeader(doc);
191 secHeader.insertSecurityHeader();
192
193 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
194 builder.setPasswordsAreEncoded(true);
195 byte[] bytes = MessageDigest.getInstance("SHA-1").digest("security".getBytes(StandardCharsets.UTF_8));
196 builder.setUserInfo("bob", org.apache.xml.security.utils.XMLUtils.encodeToString(bytes));
197 builder.addDerivedKey(1000);
198 byte[] salt = UsernameTokenUtil.generateSalt(false);
199 builder.prepare(salt);
200
201 byte[] derivedKey = builder.getDerivedKey(salt);
202 assertTrue(derivedKey.length == 20);
203 String tokenIdentifier = builder.getId();
204
205
206
207
208 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
209 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
210 encrBuilder.setTokenIdentifier(tokenIdentifier);
211 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
212 Document encryptedDoc = encrBuilder.build(derivedKey);
213
214 builder.prependToHeader();
215
216 String outputString =
217 XMLUtils.prettyDocumentToString(encryptedDoc);
218 assertTrue(outputString.contains("wsse:Username"));
219 assertFalse(outputString.contains("wsse:Password"));
220 assertTrue(outputString.contains("wsse11:Salt"));
221 assertTrue(outputString.contains("wsse11:Iteration"));
222 assertFalse(outputString.contains("testMethod"));
223 if (LOG.isDebugEnabled()) {
224 LOG.debug(outputString);
225 }
226
227 RequestData requestData = new RequestData();
228 requestData.setEncodePasswords(true);
229 requestData.setAllowUsernameTokenNoPassword(true);
230 requestData.setCallbackHandler(new EncodedPasswordCallbackHandler());
231
232 WSSecurityEngine newEngine = new WSSecurityEngine();
233 newEngine.processSecurityHeader(encryptedDoc, requestData);
234 }
235
236
237
238
239
240 @Test
241 public void testDerivedKeyChangedEncryption() throws Exception {
242 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
243 WSSecHeader secHeader = new WSSecHeader(doc);
244 secHeader.insertSecurityHeader();
245
246 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
247 builder.setUserInfo("bob", "security");
248 builder.addDerivedKey(1000);
249 byte[] salt = UsernameTokenUtil.generateSalt(false);
250 builder.prepare(salt);
251
252 byte[] derivedKey = builder.getDerivedKey(salt);
253 derivedKey[5] = 'z';
254 derivedKey[6] = 'a';
255 assertTrue(derivedKey.length == 20);
256
257 String tokenIdentifier = builder.getId();
258
259
260
261
262 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
263 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
264 encrBuilder.setTokenIdentifier(tokenIdentifier);
265 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
266 Document encryptedDoc = encrBuilder.build(derivedKey);
267
268 builder.prependToHeader();
269
270 String outputString =
271 XMLUtils.prettyDocumentToString(encryptedDoc);
272 assertTrue(outputString.contains("wsse:Username"));
273 assertFalse(outputString.contains("wsse:Password"));
274 assertTrue(outputString.contains("wsse11:Salt"));
275 assertTrue(outputString.contains("wsse11:Iteration"));
276 assertFalse(outputString.contains("testMethod"));
277 if (LOG.isDebugEnabled()) {
278 LOG.debug(outputString);
279 }
280
281 try {
282 verify(encryptedDoc);
283 fail("Failure expected on a bad derived encryption");
284 } catch (WSSecurityException ex) {
285 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_CHECK);
286 }
287 }
288
289
290
291
292
293 @Test
294 public void testDerivedKeyBadUserEncryption() throws Exception {
295 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
296 WSSecHeader secHeader = new WSSecHeader(doc);
297 secHeader.insertSecurityHeader();
298
299 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
300 builder.setUserInfo("colm", "security");
301 builder.addDerivedKey(1000);
302 byte[] salt = UsernameTokenUtil.generateSalt(false);
303 builder.prepare(salt);
304
305 byte[] derivedKey = builder.getDerivedKey(salt);
306 assertTrue(derivedKey.length == 20);
307
308 String tokenIdentifier = builder.getId();
309
310
311
312
313 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
314 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
315 encrBuilder.setTokenIdentifier(tokenIdentifier);
316 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
317 Document encryptedDoc = encrBuilder.build(derivedKey);
318
319 builder.prependToHeader();
320
321 String outputString =
322 XMLUtils.prettyDocumentToString(encryptedDoc);
323 assertTrue(outputString.contains("wsse:Username"));
324 assertFalse(outputString.contains("wsse:Password"));
325 assertTrue(outputString.contains("wsse11:Salt"));
326 assertTrue(outputString.contains("wsse11:Iteration"));
327 assertFalse(outputString.contains("testMethod"));
328 if (LOG.isDebugEnabled()) {
329 LOG.debug(outputString);
330 }
331
332 try {
333 verify(encryptedDoc);
334 fail("Failure expected on a bad derived encryption");
335 } catch (WSSecurityException ex) {
336 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
337 }
338 }
339
340
341
342
343 @Test
344 public void testDerivedKeySignature() throws Exception {
345 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
346 WSSecHeader secHeader = new WSSecHeader(doc);
347 secHeader.insertSecurityHeader();
348
349 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
350 builder.setUserInfo("bob", "security");
351 builder.addDerivedKey(1000);
352 byte[] salt = UsernameTokenUtil.generateSalt(true);
353 builder.prepare(salt);
354
355 byte[] derivedKey = builder.getDerivedKey(salt);
356 assertTrue(derivedKey.length == 20);
357
358 String tokenIdentifier = builder.getId();
359
360
361
362
363 WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
364 sigBuilder.setTokenIdentifier(tokenIdentifier);
365 sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
366 sigBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
367 Document signedDoc = sigBuilder.build(derivedKey);
368
369 builder.prependToHeader();
370
371 String outputString =
372 XMLUtils.prettyDocumentToString(signedDoc);
373 assertTrue(outputString.contains("wsse:Username"));
374 assertFalse(outputString.contains("wsse:Password"));
375 assertTrue(outputString.contains("wsse11:Salt"));
376 assertTrue(outputString.contains("wsse11:Iteration"));
377 if (LOG.isDebugEnabled()) {
378 LOG.debug(outputString);
379 }
380
381 WSHandlerResult results = verify(signedDoc);
382 WSSecurityEngineResult actionResult =
383 results.getActionResults().get(WSConstants.SIGN).get(0);
384 java.security.Principal principal =
385 (java.security.Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
386
387 assertTrue(principal.getName().contains("DK"));
388 }
389
390
391
392
393 @Test
394 public void testDerivedKeySignatureWithEncodedPassword() throws Exception {
395 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
396 WSSecHeader secHeader = new WSSecHeader(doc);
397 secHeader.insertSecurityHeader();
398
399 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
400 builder.setPasswordsAreEncoded(true);
401 byte[] bytes = MessageDigest.getInstance("SHA-1").digest("security".getBytes(StandardCharsets.UTF_8));
402 builder.setUserInfo("bob", org.apache.xml.security.utils.XMLUtils.encodeToString(bytes));
403 builder.addDerivedKey(1000);
404 byte[] salt = UsernameTokenUtil.generateSalt(true);
405 builder.prepare(salt);
406
407 byte[] derivedKey = builder.getDerivedKey(salt);
408 assertTrue(derivedKey.length == 20);
409
410 String tokenIdentifier = builder.getId();
411
412
413
414
415 WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
416 sigBuilder.setTokenIdentifier(tokenIdentifier);
417 sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
418 sigBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
419 Document signedDoc = sigBuilder.build(derivedKey);
420
421 builder.prependToHeader();
422
423 String outputString =
424 XMLUtils.prettyDocumentToString(signedDoc);
425 assertTrue(outputString.contains("wsse:Username"));
426 assertFalse(outputString.contains("wsse:Password"));
427 assertTrue(outputString.contains("wsse11:Salt"));
428 assertTrue(outputString.contains("wsse11:Iteration"));
429 if (LOG.isDebugEnabled()) {
430 LOG.debug(outputString);
431 }
432
433 RequestData requestData = new RequestData();
434 requestData.setEncodePasswords(true);
435 requestData.setAllowUsernameTokenNoPassword(true);
436 requestData.setCallbackHandler(new EncodedPasswordCallbackHandler());
437
438 WSSecurityEngine newEngine = new WSSecurityEngine();
439 WSHandlerResult results = newEngine.processSecurityHeader(signedDoc, requestData);
440
441 WSSecurityEngineResult actionResult =
442 results.getActionResults().get(WSConstants.SIGN).get(0);
443 java.security.Principal principal =
444 (java.security.Principal) actionResult.get(WSSecurityEngineResult.TAG_PRINCIPAL);
445
446 assertTrue(principal.getName().contains("DK"));
447 }
448
449
450
451
452
453
454 @Test
455 public void testDerivedKeyChangedSignature() throws Exception {
456 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
457 WSSecHeader secHeader = new WSSecHeader(doc);
458 secHeader.insertSecurityHeader();
459
460 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
461 builder.setUserInfo("bob", "security");
462 builder.addDerivedKey(1000);
463 byte[] salt = UsernameTokenUtil.generateSalt(true);
464 builder.prepare(salt);
465
466 byte[] derivedKey = builder.getDerivedKey(salt);
467 if (derivedKey[5] != 12) {
468 derivedKey[5] = 12;
469 } else {
470 derivedKey[5] = 13;
471 }
472 assertTrue(derivedKey.length == 20);
473
474 String tokenIdentifier = builder.getId();
475
476
477
478
479 WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
480 sigBuilder.setTokenIdentifier(tokenIdentifier);
481 sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
482 sigBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
483 Document signedDoc = sigBuilder.build(derivedKey);
484
485 builder.prependToHeader();
486
487 String outputString =
488 XMLUtils.prettyDocumentToString(signedDoc);
489 if (LOG.isDebugEnabled()) {
490 LOG.debug(outputString);
491 }
492
493 try {
494 verify(signedDoc);
495 fail("Failure expected on a bad derived signature");
496 } catch (WSSecurityException ex) {
497 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_CHECK);
498 }
499 }
500
501
502
503
504
505 @Test
506 public void testDerivedKeyBadUserSignature() throws Exception {
507 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
508 WSSecHeader secHeader = new WSSecHeader(doc);
509 secHeader.insertSecurityHeader();
510
511 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
512 builder.setUserInfo("colm", "security");
513 builder.addDerivedKey(1000);
514 byte[] salt = UsernameTokenUtil.generateSalt(true);
515 builder.prepare(salt);
516
517 byte[] derivedKey = builder.getDerivedKey(salt);
518 assertTrue(derivedKey.length == 20);
519
520 String tokenIdentifier = builder.getId();
521
522
523
524
525 WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
526 sigBuilder.setTokenIdentifier(tokenIdentifier);
527 sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
528 sigBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
529 Document signedDoc = sigBuilder.build(derivedKey);
530
531 builder.prependToHeader();
532
533 String outputString =
534 XMLUtils.prettyDocumentToString(signedDoc);
535 if (LOG.isDebugEnabled()) {
536 LOG.debug(outputString);
537 }
538
539 try {
540 verify(signedDoc);
541 fail("Failure expected on a bad derived signature");
542 } catch (WSSecurityException ex) {
543 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILED_AUTHENTICATION);
544 }
545 }
546
547
548
549
550
551 @Test
552 public void testNoSaltEncryption() throws Exception {
553 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
554 WSSecHeader secHeader = new WSSecHeader(doc);
555 secHeader.insertSecurityHeader();
556
557 UsernameToken usernameToken = new UsernameToken(true, doc, null);
558 usernameToken.setName("bob");
559 WSSConfig config = WSSConfig.getNewInstance();
560 usernameToken.setID(config.getIdAllocator().createId("UsernameToken-", usernameToken));
561
562 byte[] salt = UsernameTokenUtil.generateSalt(false);
563 usernameToken.addIteration(doc, 1000);
564
565 byte[] derivedKey = UsernameTokenUtil.generateDerivedKey("security", salt, 1000);
566
567
568
569
570 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
571 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
572 encrBuilder.setTokenIdentifier(usernameToken.getID());
573 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
574 Document encryptedDoc = encrBuilder.build(derivedKey);
575
576 WSSecurityUtil.prependChildElement(
577 secHeader.getSecurityHeaderElement(), usernameToken.getElement()
578 );
579
580 String outputString =
581 XMLUtils.prettyDocumentToString(doc);
582 assertTrue(outputString.contains("wsse:Username"));
583 assertFalse(outputString.contains("wsse:Password"));
584 assertFalse(outputString.contains("wsse11:Salt"));
585 assertTrue(outputString.contains("wsse11:Iteration"));
586 if (LOG.isDebugEnabled()) {
587 LOG.debug(outputString);
588 }
589
590 try {
591 verify(encryptedDoc);
592 fail("Failure expected on no salt element");
593 } catch (WSSecurityException ex) {
594 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.FAILURE);
595 }
596 }
597
598
599
600
601
602 @Test
603 public void testNoIterationEncryption() throws Exception {
604 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
605 WSSecHeader secHeader = new WSSecHeader(doc);
606 secHeader.insertSecurityHeader();
607
608 UsernameToken usernameToken = new UsernameToken(true, doc, null);
609 usernameToken.setName("bob");
610 WSSConfig config = WSSConfig.getNewInstance();
611 usernameToken.setID(config.getIdAllocator().createId("UsernameToken-", usernameToken));
612
613 byte[] salt = UsernameTokenUtil.generateSalt(false);
614 usernameToken.addSalt(doc, salt);
615 byte[] derivedKey = UsernameTokenUtil.generateDerivedKey("security", salt, 1000);
616
617
618
619
620 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
621 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
622 encrBuilder.setTokenIdentifier(usernameToken.getID());
623 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
624 Document encryptedDoc = encrBuilder.build(derivedKey);
625
626 WSSecurityUtil.prependChildElement(
627 secHeader.getSecurityHeaderElement(), usernameToken.getElement()
628 );
629
630 String outputString =
631 XMLUtils.prettyDocumentToString(doc);
632 assertTrue(outputString.contains("wsse:Username"));
633 assertFalse(outputString.contains("wsse:Password"));
634 assertTrue(outputString.contains("wsse11:Salt"));
635 assertFalse(outputString.contains("wsse11:Iteration"));
636 if (LOG.isDebugEnabled()) {
637 LOG.debug(outputString);
638 }
639
640 try {
641 verify(encryptedDoc);
642 fail("Failure expected on no iteration element");
643 } catch (WSSecurityException ex) {
644 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY_TOKEN);
645 }
646 }
647
648
649
650
651
652 @Test
653 public void testLowIterationEncryption() throws Exception {
654 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
655 WSSecHeader secHeader = new WSSecHeader(doc);
656 secHeader.insertSecurityHeader();
657
658 UsernameToken usernameToken = new UsernameToken(true, doc, null);
659 usernameToken.setName("bob");
660 WSSConfig config = WSSConfig.getNewInstance();
661 usernameToken.setID(config.getIdAllocator().createId("UsernameToken-", usernameToken));
662
663 usernameToken.addIteration(doc, 500);
664 byte[] salt = UsernameTokenUtil.generateSalt(false);
665 usernameToken.addSalt(doc, salt);
666 byte[] derivedKey = UsernameTokenUtil.generateDerivedKey("security", salt, 500);
667
668
669
670
671 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
672 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
673 encrBuilder.setTokenIdentifier(usernameToken.getID());
674 encrBuilder.setCustomValueType(WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE);
675 Document encryptedDoc = encrBuilder.build(derivedKey);
676
677 WSSecurityUtil.prependChildElement(
678 secHeader.getSecurityHeaderElement(), usernameToken.getElement()
679 );
680
681 String outputString =
682 XMLUtils.prettyDocumentToString(doc);
683 assertTrue(outputString.contains("wsse:Username"));
684 assertFalse(outputString.contains("wsse:Password"));
685 assertTrue(outputString.contains("wsse11:Salt"));
686 assertTrue(outputString.contains("wsse11:Iteration"));
687 if (LOG.isDebugEnabled()) {
688 LOG.debug(outputString);
689 }
690
691 try {
692 verify(encryptedDoc);
693 fail("Failure expected on a low iteration value");
694 } catch (WSSecurityException ex) {
695 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
696 }
697
698 RequestData data = new RequestData();
699 data.setCallbackHandler(callbackHandler);
700 data.setDecCrypto(crypto);
701 data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R4218));
702 data.setAllowUsernameTokenNoPassword(true);
703
704 WSSecurityEngine engine = new WSSecurityEngine();
705 engine.setWssConfig(config);
706 engine.processSecurityHeader(doc, data);
707 }
708
709
710
711
712
713
714
715 @Test
716 public void testBadValueType() throws Exception {
717 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
718 WSSecHeader secHeader = new WSSecHeader(doc);
719 secHeader.insertSecurityHeader();
720
721 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
722 builder.setUserInfo("bob", "security");
723 builder.addDerivedKey(1000);
724 byte[] salt = UsernameTokenUtil.generateSalt(false);
725 builder.prepare(salt);
726
727 byte[] derivedKey = builder.getDerivedKey(salt);
728 assertTrue(derivedKey.length == 20);
729
730 String tokenIdentifier = builder.getId();
731
732
733
734
735 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
736 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
737 encrBuilder.setTokenIdentifier(tokenIdentifier);
738 encrBuilder.setCustomValueType(WSConstants.WSS_SAML_TOKEN_TYPE);
739 Document encryptedDoc = encrBuilder.build(derivedKey);
740
741 builder.prependToHeader();
742
743 String outputString =
744 XMLUtils.prettyDocumentToString(encryptedDoc);
745 assertTrue(outputString.contains("wsse:Username"));
746 assertFalse(outputString.contains("wsse:Password"));
747 assertTrue(outputString.contains("wsse11:Salt"));
748 assertTrue(outputString.contains("wsse11:Iteration"));
749 assertFalse(outputString.contains("testMethod"));
750 if (LOG.isDebugEnabled()) {
751 LOG.debug(outputString);
752 }
753
754 try {
755 verify(encryptedDoc);
756 fail("Failure expected on a bad value type");
757 } catch (WSSecurityException ex) {
758 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
759 }
760
761
762 RequestData data = new RequestData();
763 data.setCallbackHandler(callbackHandler);
764 data.setDecCrypto(crypto);
765 data.setAllowUsernameTokenNoPassword(true);
766
767 WSSConfig config = WSSConfig.getNewInstance();
768 WSSecurityEngine newEngine = new WSSecurityEngine();
769 newEngine.setWssConfig(config);
770 data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R4214));
771 newEngine.processSecurityHeader(encryptedDoc, data);
772 }
773
774
775
776
777
778
779 @Test
780 public void testKeyIdentifier() throws Exception {
781 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
782 WSSecHeader secHeader = new WSSecHeader(doc);
783 secHeader.insertSecurityHeader();
784
785 WSSecUsernameToken builder = new WSSecUsernameToken(secHeader);
786 builder.setUserInfo("bob", "security");
787 builder.addDerivedKey(1000);
788 byte[] salt = UsernameTokenUtil.generateSalt(false);
789 builder.prepare(salt);
790
791 byte[] derivedKey = builder.getDerivedKey(salt);
792 assertTrue(derivedKey.length == 20);
793
794 String tokenIdentifier = builder.getId();
795
796
797
798
799 WSSecDKEncrypt encrBuilder = new WSSecDKEncrypt(secHeader);
800 encrBuilder.setSymmetricEncAlgorithm(WSConstants.AES_128);
801
802 SecurityTokenReference strEncKey = new SecurityTokenReference(doc);
803 strEncKey.setKeyIdentifier(
804 WSConstants.WSS_USERNAME_TOKEN_VALUE_TYPE, tokenIdentifier, true
805 );
806 encrBuilder.setStrElem(strEncKey.getElement());
807 Document encryptedDoc = encrBuilder.build(derivedKey);
808
809 builder.prependToHeader();
810
811 String outputString =
812 XMLUtils.prettyDocumentToString(encryptedDoc);
813 assertTrue(outputString.contains("wsse:Username"));
814 assertFalse(outputString.contains("wsse:Password"));
815 assertTrue(outputString.contains("wsse11:Salt"));
816 assertTrue(outputString.contains("wsse11:Iteration"));
817 assertFalse(outputString.contains("testMethod"));
818 if (LOG.isDebugEnabled()) {
819 LOG.debug(outputString);
820 }
821
822 try {
823 verify(encryptedDoc);
824 fail("Failure expected on a key identifier");
825 } catch (WSSecurityException ex) {
826 assertTrue(ex.getErrorCode() == WSSecurityException.ErrorCode.INVALID_SECURITY);
827 }
828
829 WSSecurityEngine newEngine = new WSSecurityEngine();
830 RequestData data = new RequestData();
831 data.setCallbackHandler(callbackHandler);
832 data.setDecCrypto(crypto);
833 data.setIgnoredBSPRules(Collections.singletonList(BSPRule.R4215));
834 data.setAllowUsernameTokenNoPassword(true);
835
836 WSSConfig config = WSSConfig.getNewInstance();
837 newEngine.setWssConfig(config);
838 newEngine.processSecurityHeader(encryptedDoc, data);
839 }
840
841
842
843
844
845
846
847
848 private WSHandlerResult verify(Document doc) throws Exception {
849 return verify(doc, true);
850 }
851
852 private WSHandlerResult verify(
853 Document doc,
854 boolean allowUsernameTokenDerivedKeys
855 ) throws Exception {
856 WSSecurityEngine secEngine = new WSSecurityEngine();
857
858 RequestData requestData = new RequestData();
859 requestData.setAllowUsernameTokenNoPassword(allowUsernameTokenDerivedKeys);
860 requestData.setCallbackHandler(callbackHandler);
861 requestData.setDecCrypto(crypto);
862 requestData.setSigVerCrypto(crypto);
863
864 return secEngine.processSecurityHeader(doc, requestData);
865 }
866
867 }