1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.ws.security.message.token;
21
22 import java.security.Principal;
23 import java.util.HashMap;
24 import java.util.Map;
25
26 import javax.xml.namespace.QName;
27
28 import org.apache.ws.security.WSConstants;
29 import org.apache.ws.security.WSDerivedKeyTokenPrincipal;
30 import org.apache.ws.security.WSSecurityException;
31 import org.apache.ws.security.conversation.ConversationConstants;
32 import org.apache.ws.security.conversation.ConversationException;
33 import org.apache.ws.security.conversation.dkalgo.AlgoFactory;
34 import org.apache.ws.security.conversation.dkalgo.DerivationAlgorithm;
35 import org.apache.ws.security.util.Base64;
36 import org.apache.ws.security.util.DOM2Writer;
37 import org.apache.ws.security.util.WSSecurityUtil;
38 import org.w3c.dom.Document;
39 import org.w3c.dom.Element;
40 import org.w3c.dom.Node;
41 import org.w3c.dom.Text;
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59 public class DerivedKeyToken {
60
61 private static org.apache.commons.logging.Log log =
62 org.apache.commons.logging.LogFactory.getLog(DerivedKeyToken.class);
63
64
65 protected Element element = null;
66 protected Element elementSecurityTokenReference = null;
67 protected Element elementProperties = null;
68 protected Element elementGeneration = null;
69 protected Element elementOffset = null;
70 protected Element elementLength = null;
71 protected Element elementLabel = null;
72 protected Element elementNonce = null;
73
74 private String ns;
75 private boolean bspCompliant = true;
76
77
78
79
80
81
82 public DerivedKeyToken(Document doc) throws ConversationException {
83 this(ConversationConstants.DEFAULT_VERSION, doc);
84 }
85
86
87
88
89
90
91 public DerivedKeyToken(int version, Document doc) throws ConversationException {
92 log.debug("DerivedKeyToken: created");
93
94 ns = ConversationConstants.getWSCNs(version);
95 element =
96 doc.createElementNS(ns, "wsc:" + ConversationConstants.DERIVED_KEY_TOKEN_LN);
97 WSSecurityUtil.setNamespace(element, ns, ConversationConstants.WSC_PREFIX);
98 }
99
100
101
102
103
104
105
106 public DerivedKeyToken(Element elem) throws WSSecurityException {
107 this(elem, true);
108 }
109
110
111
112
113
114
115
116
117 public DerivedKeyToken(Element elem, boolean bspCompliant) throws WSSecurityException {
118 log.debug("DerivedKeyToken: created : element constructor");
119 element = elem;
120 this.bspCompliant = bspCompliant;
121 QName el = new QName(element.getNamespaceURI(), element.getLocalName());
122
123 if (!(el.equals(ConversationConstants.DERIVED_KEY_TOKEN_QNAME_05_02) ||
124 el.equals(ConversationConstants.DERIVED_KEY_TOKEN_QNAME_05_12))) {
125 throw new WSSecurityException(
126 WSSecurityException.INVALID_SECURITY_TOKEN
127 );
128 }
129 elementSecurityTokenReference =
130 WSSecurityUtil.getDirectChildElement(
131 element,
132 ConversationConstants.SECURITY_TOKEN_REFERENCE_LN,
133 WSConstants.WSSE_NS
134 );
135
136 ns = el.getNamespaceURI();
137
138 elementProperties =
139 WSSecurityUtil.getDirectChildElement(
140 element, ConversationConstants.PROPERTIES_LN, ns
141 );
142 elementGeneration =
143 WSSecurityUtil.getDirectChildElement(
144 element, ConversationConstants.GENERATION_LN, ns
145 );
146 elementOffset =
147 WSSecurityUtil.getDirectChildElement(
148 element, ConversationConstants.OFFSET_LN, ns
149 );
150 elementLength =
151 WSSecurityUtil.getDirectChildElement(
152 element, ConversationConstants.LENGTH_LN, ns
153 );
154 elementLabel =
155 WSSecurityUtil.getDirectChildElement(
156 element, ConversationConstants.LABEL_LN, ns
157 );
158 elementNonce =
159 WSSecurityUtil.getDirectChildElement(
160 element, ConversationConstants.NONCE_LN, ns
161 );
162 }
163
164
165
166
167
168 public void addWSUNamespace() {
169 WSSecurityUtil.setNamespace(element, WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
170 }
171
172
173
174
175
176
177
178 public void setSecurityTokenReference(SecurityTokenReference ref) {
179 elementSecurityTokenReference = ref.getElement();
180 WSSecurityUtil.prependChildElement(element, ref.getElement());
181 }
182
183 public void setSecurityTokenReference(Element elem) {
184 elementSecurityTokenReference = elem;
185 WSSecurityUtil.prependChildElement(element, elem);
186 }
187
188
189
190
191
192
193
194 public SecurityTokenReference getSecurityTokenReference() throws WSSecurityException {
195 if (elementSecurityTokenReference != null) {
196 return new SecurityTokenReference(elementSecurityTokenReference, bspCompliant);
197 }
198 return null;
199 }
200
201
202
203
204
205
206 public Element getSecurityTokenReferenceElement() {
207 return elementSecurityTokenReference;
208 }
209
210
211
212
213
214
215
216
217 private void addProperty(String propName, String propValue) {
218 if (elementProperties == null) {
219 elementProperties =
220 element.getOwnerDocument().createElementNS(
221 ns, "wsc:" + ConversationConstants.PROPERTIES_LN
222 );
223 element.appendChild(elementProperties);
224 }
225 Element tempElement =
226 element.getOwnerDocument().createElementNS(ns, "wsc:" + propName);
227 tempElement.appendChild(element.getOwnerDocument().createTextNode(propValue));
228
229 elementProperties.appendChild(tempElement);
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243 public void setProperties(String name, String label, String nonce) {
244 Map<String, String> table = new HashMap<String, String>();
245 table.put("Name", name);
246 table.put("Label", label);
247 table.put("Nonce", nonce);
248 setProperties(table);
249 }
250
251
252
253
254
255
256
257 public void setProperties(Map<String, String> properties) {
258 for (String key : properties.keySet()) {
259 String propertyName = properties.get(key);
260
261
262 Element node =
263 WSSecurityUtil.findElement(elementProperties, propertyName, ns);
264 if (node != null) {
265 Text node1 = getFirstNode(node);
266 node1.setData(properties.get(propertyName));
267 } else {
268 addProperty(propertyName, properties.get(propertyName));
269 }
270 }
271 }
272
273 public Map<String, String> getProperties() {
274 if (elementProperties != null) {
275 Map<String, String> table = new HashMap<String, String>();
276 Node node = elementProperties.getFirstChild();
277 while (node != null) {
278 if (Node.ELEMENT_NODE == node.getNodeType()) {
279 Text text = getFirstNode((Element) node);
280 table.put(node.getNodeName(), text.getData());
281 }
282 node = node.getNextSibling();
283 }
284 }
285 return null;
286 }
287
288
289
290
291
292
293 public void setLength(int length) {
294 elementLength =
295 element.getOwnerDocument().createElementNS(
296 ns, "wsc:" + ConversationConstants.LENGTH_LN
297 );
298 elementLength.appendChild(
299 element.getOwnerDocument().createTextNode(Long.toString(length))
300 );
301 element.appendChild(elementLength);
302 }
303
304 public int getLength() {
305 if (elementLength != null) {
306 return Integer.parseInt(getFirstNode(elementLength).getData());
307 }
308 return 32;
309 }
310
311
312
313
314
315
316 public void setOffset(int offset) throws ConversationException {
317
318 if (elementGeneration == null) {
319 elementOffset =
320 element.getOwnerDocument().createElementNS(
321 ns, "wsc:" + ConversationConstants.OFFSET_LN
322 );
323 elementOffset.appendChild(
324 element.getOwnerDocument().createTextNode(Integer.toString(offset))
325 );
326 element.appendChild(elementOffset);
327 } else {
328 throw new ConversationException(
329 "Offset cannot be set along with generation - generation is already set"
330 );
331 }
332
333 }
334
335 public int getOffset() {
336 if (elementOffset != null) {
337 return Integer.parseInt(getFirstNode(elementOffset).getData());
338 }
339 return 0;
340 }
341
342
343
344
345
346
347 public void setGeneration(int generation) throws ConversationException {
348
349 if (elementOffset == null) {
350 elementGeneration =
351 element.getOwnerDocument().createElementNS(
352 ns, "wsc:" + ConversationConstants.GENERATION_LN
353 );
354 elementGeneration.appendChild(
355 element.getOwnerDocument().createTextNode(Integer.toString(generation))
356 );
357 element.appendChild(elementGeneration);
358 } else {
359 throw new ConversationException(
360 "Generation cannot be set along with offset - Offset is already set"
361 );
362 }
363 }
364
365 public int getGeneration() {
366 if (elementGeneration != null) {
367 return Integer.parseInt(getFirstNode(elementGeneration).getData());
368 }
369 return -1;
370 }
371
372
373
374
375
376
377 public void setLabel(String label) {
378 elementLabel =
379 element.getOwnerDocument().createElementNS(
380 ns, "wsc:" + ConversationConstants.LABEL_LN
381 );
382 elementLabel.appendChild(element.getOwnerDocument().createTextNode(label));
383 element.appendChild(elementLabel);
384 }
385
386
387
388
389
390
391 public void setNonce(String nonce) {
392 elementNonce =
393 element.getOwnerDocument().createElementNS(
394 ns, "wsc:" + ConversationConstants.NONCE_LN
395 );
396 elementNonce.appendChild(element.getOwnerDocument().createTextNode(nonce));
397 element.appendChild(elementNonce);
398 }
399
400
401
402
403
404
405 public String getLabel() {
406 if (elementLabel != null) {
407 return getFirstNode(elementLabel).getData();
408 }
409 return null;
410 }
411
412
413
414
415
416
417 public String getNonce() {
418 if (elementNonce != null) {
419 return getFirstNode(elementNonce).getData();
420 }
421 return null;
422 }
423
424
425
426
427
428
429
430
431 private Text getFirstNode(Element e) {
432 Node node = e.getFirstChild();
433 return (node != null && Node.TEXT_NODE == node.getNodeType()) ? (Text) node : null;
434 }
435
436
437
438
439
440
441 public Element getElement() {
442 return element;
443 }
444
445
446
447
448
449
450 public String toString() {
451 return DOM2Writer.nodeToString((Node)element);
452 }
453
454
455
456
457
458
459
460 public String getID() {
461 return element.getAttributeNS(WSConstants.WSU_NS, "Id");
462 }
463
464
465
466
467
468
469
470 public void setID(String id) {
471 element.setAttributeNS(WSConstants.WSU_NS, WSConstants.WSU_PREFIX + ":Id", id);
472 }
473
474
475
476
477
478
479
480 public String getAlgorithm() {
481 String algo = element.getAttributeNS(ns, "Algorithm");
482 if (algo == null || algo.equals("")) {
483 return ConversationConstants.DerivationAlgorithm.P_SHA_1;
484 } else {
485 return algo;
486 }
487 }
488
489
490
491
492 public Principal createPrincipal() throws WSSecurityException {
493 WSDerivedKeyTokenPrincipal principal = new WSDerivedKeyTokenPrincipal(getID());
494 principal.setNonce(getNonce());
495 principal.setLabel(getLabel());
496 principal.setLength(getLength());
497 principal.setOffset(getOffset());
498 principal.setAlgorithm(getAlgorithm());
499
500 String basetokenId = null;
501 SecurityTokenReference securityTokenReference = getSecurityTokenReference();
502 if (securityTokenReference.containsReference()) {
503 basetokenId = securityTokenReference.getReference().getURI();
504 if (basetokenId.charAt(0) == '#') {
505 basetokenId = basetokenId.substring(1);
506 }
507 } else {
508
509 basetokenId = securityTokenReference.getKeyIdentifierValue();
510 }
511 principal.setBasetokenId(basetokenId);
512
513 return principal;
514 }
515
516
517
518
519
520
521
522 public void setAlgorithm(String algo) {
523 element.setAttributeNS(ns, "Algorithm", algo);
524 }
525
526
527
528
529
530
531
532 public byte[] deriveKey(int length, byte[] secret) throws WSSecurityException {
533 try {
534 DerivationAlgorithm algo = AlgoFactory.getInstance(getAlgorithm());
535 byte[] labelBytes = null;
536 String label = getLabel();
537 if (label == null || label.length() == 0) {
538 labelBytes =
539 (ConversationConstants.DEFAULT_LABEL
540 + ConversationConstants.DEFAULT_LABEL).getBytes("UTF-8");
541 } else {
542 labelBytes = label.getBytes("UTF-8");
543 }
544
545 byte[] nonce = Base64.decode(getNonce());
546 byte[] seed = new byte[labelBytes.length + nonce.length];
547 System.arraycopy(labelBytes, 0, seed, 0, labelBytes.length);
548 System.arraycopy(nonce, 0, seed, labelBytes.length, nonce.length);
549
550 if (length <= 0) {
551 length = getLength();
552 }
553 return algo.createKey(secret, seed, getOffset(), length);
554
555 } catch (Exception e) {
556 throw new WSSecurityException(
557 WSSecurityException.FAILURE, null, null, e
558 );
559 }
560 }
561
562 @Override
563 public int hashCode() {
564 int result = 17;
565 String algorithm = getAlgorithm();
566 if (algorithm != null) {
567 result = 31 * result + algorithm.hashCode();
568 }
569 try {
570 SecurityTokenReference tokenReference = getSecurityTokenReference();
571 if (tokenReference != null) {
572 result = 31 * result + tokenReference.hashCode();
573 }
574 } catch (WSSecurityException e) {
575 log.error(e);
576 }
577
578 Map<String, String> properties = getProperties();
579 if (properties != null) {
580 result = 31 * result + properties.hashCode();
581 }
582 int generation = getGeneration();
583 if (generation != -1) {
584 result = 31 * result + generation;
585 }
586 int offset = getOffset();
587 if (offset != -1) {
588 result = 31 * result + offset;
589 }
590 int length = getLength();
591 if (length != -1) {
592 result = 31 * result + length;
593 }
594 String label = getLabel();
595 if (label != null) {
596 result = 31 * result + label.hashCode();
597 }
598 String nonce = getNonce();
599 if (nonce != null) {
600 result = 31 * result + nonce.hashCode();
601 }
602
603 return result;
604 }
605
606 @Override
607 public boolean equals(Object object) {
608 if (!(object instanceof DerivedKeyToken)) {
609 return false;
610 }
611 DerivedKeyToken token = (DerivedKeyToken)object;
612 if (!compare(getAlgorithm(), token.getAlgorithm())) {
613 return false;
614 }
615 try {
616 if (!getSecurityTokenReference().equals(token.getSecurityTokenReference())) {
617 return false;
618 }
619 } catch (WSSecurityException e) {
620 log.error(e);
621 return false;
622 }
623 if (!compare(getProperties(), token.getProperties())) {
624 return false;
625 }
626 if (getGeneration() != token.getGeneration()) {
627 return false;
628 }
629 if (getOffset() != token.getOffset()) {
630 return false;
631 }
632 if (getLength() != token.getLength()) {
633 return false;
634 }
635 if (!compare(getLabel(), token.getLabel())) {
636 return false;
637 }
638 if (!compare(getNonce(), token.getNonce())) {
639 return false;
640 }
641 return true;
642 }
643
644 private boolean compare(String item1, String item2) {
645 if (item1 == null && item2 != null) {
646 return false;
647 } else if (item1 != null && !item1.equals(item2)) {
648 return false;
649 }
650 return true;
651 }
652
653 private boolean compare(Map<String, String> item1, Map<String, String> item2) {
654 if (item1 == null && item2 != null) {
655 return false;
656 } else if (item1 != null && !item1.equals(item2)) {
657 return false;
658 }
659 return true;
660 }
661 }