1 package iaik.pkcs.pkcs11.objects;
2 
3 import iaik.pkcs.pkcs11.Session;
4 import iaik.pkcs.pkcs11.TokenException;
5 import iaik.pkcs.pkcs11.wrapper.Constants;
6 import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
7 import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
8 
9 import java.util.Hashtable;
10 
11 /**
12  * An object of this class represents a key as defined by PKCS#11 2.11.
13  * A key is of a specific type: RSA, DSA, DH, ECDSA, EC, X9_42_DH, KEA,
14  * GENERIC_SECRET, RC2, RC4, DES, DES2, DES3, CAST, CAST3, CAST5, CAST128,
15  * RC5, IDEA, SKIPJACK, BATON, JUNIPER, CDMF, AES or VENDOR_DEFINED.
16  * If an application needs to use vendor-defined keys,  it must set a
17  * VendorDefinedKeyeBuilder using the setVendorDefinedKeyBuilder method.
18  *
19  * @author Karl Scheibelhofer
20  * @version 1.0
21  * @invariants (keyType_ <> null)
22  *             and (id_ <> null)
23  *             and (startDate_ <> null)
24  *             and (endDate_ <> null)
25  *             and (derive_ <> null)
26  *             and (local_ <> null)
27  *             and (keyGenMechanism_ <> null)
28  */
29 public class Key extends Storage {
30 
31 	/**
32 	 * This interface defines the available key types as defined by PKCS#11 2.11:
33 	 * RSA, DSA, DH, ECDSA, KEA, GENERIC_SECRET, RC2, RC4, DES, DES2, DES3, CAST,
34 	 * CAST3, CAST5, CAST128, RC5, IDEA, SKIPJACK, BATON, JUNIPER, CDMF, AES,
35 	 * EC, X9_42_DH or VENDOR_DEFINED.
36 	 *
37 	 * @author Karl Scheibelhofer
38 	 * @version 1.0
39 	 * @invariants
40 	 */
41 	public interface KeyType {
42 
43 		/**
44 		 * The identifier for a RSA key.
45 		 */
46 		static public final Long RSA = new Long(PKCS11Constants.CKK_RSA);
47 
48 		/**
49 		 * The identifier for a DSA key.
50 		 */
51 		static public final Long DSA = new Long(PKCS11Constants.CKK_DSA);
52 
53 		/**
54 		 * The identifier for a Diffi-Hellman key.
55 		 */
56 		static public final Long DH = new Long(PKCS11Constants.CKK_DH);
57 
58 		/**
59 		 * The identifier for a ECDSA key.
60 		 */
61 		static public final Long ECDSA = new Long(PKCS11Constants.CKK_ECDSA);
62 
63 		/**
64 		 * The identifier for a EC key.
65 		 */
66 		static public final Long EC = new Long(PKCS11Constants.CKK_EC);
67 
68 		/**
69 		 * The identifier for a EC key.
70 		 */
71 		static public final Long X9_42_DH = new Long(PKCS11Constants.CKK_X9_42_DH);
72 
73 		/**
74 		 * The identifier for a KEA key.
75 		 */
76 		static public final Long KEA = new Long(PKCS11Constants.CKK_KEA);
77 
78 		/**
79 		 * The identifier for a generic secret key.
80 		 */
81 		static public final Long GENERIC_SECRET = new Long(PKCS11Constants.CKK_GENERIC_SECRET);
82 
83 		/**
84 		 * The identifier for a RC2 key.
85 		 */
86 		static public final Long RC2 = new Long(PKCS11Constants.CKK_RC2);
87 
88 		/**
89 		 * The identifier for a RC4 key.
90 		 */
91 		static public final Long RC4 = new Long(PKCS11Constants.CKK_RC4);
92 
93 		/**
94 		 * The identifier for a DES key.
95 		 */
96 		static public final Long DES = new Long(PKCS11Constants.CKK_DES);
97 
98 		/**
99 		 * The identifier for a double-length DES key.
100 		 */
101 		static public final Long DES2 = new Long(PKCS11Constants.CKK_DES2);
102 
103 		/**
104 		 * The identifier for a trible-length DES key (Trible-DES).
105 		 */
106 		static public final Long DES3 = new Long(PKCS11Constants.CKK_DES3);
107 
108 		/**
109 		 * The identifier for a CAST key.
110 		 */
111 		static public final Long CAST = new Long(PKCS11Constants.CKK_CAST);
112 
113 		/**
114 		 * The identifier for a CAST3 key.
115 		 */
116 		static public final Long CAST3 = new Long(PKCS11Constants.CKK_CAST3);
117 
118 		/**
119 		 * The identifier for a CAST5 key; CAST5 is the same as CAST128.
120 		 */
121 		static public final Long CAST5 = new Long(PKCS11Constants.CKK_CAST5);
122 
123 		/**
124 		 * The identifier for a CAST128 key.
125 		 */
126 		static public final Long CAST128 = new Long(PKCS11Constants.CKK_CAST128);
127 
128 		/**
129 		 * The identifier for a RC5 key.
130 		 */
131 		static public final Long RC5 = new Long(PKCS11Constants.CKK_RC5);
132 
133 		/**
134 		 * The identifier for a IDEA key.
135 		 */
136 		static public final Long IDEA = new Long(PKCS11Constants.CKK_IDEA);
137 
138 		/**
139 		 * The identifier for a SKIPJACK key.
140 		 */
141 		static public final Long SKIPJACK = new Long(PKCS11Constants.CKK_SKIPJACK);
142 
143 		/**
144 		 * The identifier for a BATON key.
145 		 */
146 		static public final Long BATON = new Long(PKCS11Constants.CKK_BATON);
147 
148 		/**
149 		 * The identifier for a JUNIPER key.
150 		 */
151 		static public final Long JUNIPER = new Long(PKCS11Constants.CKK_JUNIPER);
152 
153 		/**
154 		 * The identifier for a CDMF key.
155 		 */
156 		static public final Long CDMF = new Long(PKCS11Constants.CKK_CDMF);
157 
158 		/**
159 		 * The identifier for a AES key.
160 		 */
161 		static public final Long AES = new Long(PKCS11Constants.CKK_AES);
162 
163 		/**
164 		 * The identifier for a Blowfish key.
165 		 */
166 		static public final Long BLOWFISH = new Long(PKCS11Constants.CKK_BLOWFISH);
167 
168 		/**
169 		 * The identifier for a Twofish key.
170 		 */
171 		static public final Long TWOFISH = new Long(PKCS11Constants.CKK_TWOFISH);
172 
173 		/**
174 		 * The identifier for a VENDOR_DEFINED key. Any Long object with a
175 		 * value bigger than this one is also a valid vendor-defined key
176 		 * type identifier.
177 		 */
178 		static public final Long VENDOR_DEFINED = new Long(PKCS11Constants.CKK_VENDOR_DEFINED);
179 
180 	}
181 
182 	/**
183 	 * If an application uses vendor defined keys, it must implement this
184 	 * interface and install such an object handler using
185 	 * setVendorDefinedKeyBuilder.
186 	 *
187 	 * @author Karl Scheibelhofer
188 	 * @version 1.0
189 	 * @invariants
190 	 */
191 	public interface VendorDefinedKeyBuilder {
192 
193 		/**
194 		 * This method should instanciate an Object of this class or of any
195 		 * sub-class. It can use the given handles and PKCS#11 module to retrieve
196 		 * attributes of the PKCS#11 object from the token.
197 		 *
198 		 * @param session The session to use for reading attributes.
199 		 *                This session must have the appropriate rights; i.e.
200 		 *                it must be a user-session, if it is a private object.
201 		 * @param objectHandle The object handle as given from the PKCS#111 module.
202 		 * @return The object representing the PKCS#11 object.
203 		 *         The returned object can be casted to the
204 		 *         according sub-class.
205 		 * @exception PKCS11Exception If getting the attributes failed.
206 		 * @preconditions (session <> null)
207 		 * @postconditions (result <> null)
208 		 */
build(Session session, long objectHandle)209 		public Object build(Session session, long objectHandle)
210 		    throws PKCS11Exception;
211 
212 	}
213 
214 	/**
215 	 * The currently set vendor defined key builder, or null.
216 	 */
217 	protected static VendorDefinedKeyBuilder vendorKeyBuilder_;
218 
219 	/**
220 	 * A table holding string representations for all known key types. Table key
221 	 * is the key type as Long object.
222 	 */
223 	protected static Hashtable keyTypeNames_;
224 
225 	/**
226 	 * The type of this key. Its value is one of KeyType, or one that has a
227 	 * bigger value than VENDOR_DEFINED.
228 	 */
229 	protected KeyTypeAttribute keyType_;
230 
231 	/**
232 	 * The identifier (ID) of this key.
233 	 */
234 	protected ByteArrayAttribute id_;
235 
236 	/**
237 	 * The start date of this key's validity.
238 	 */
239 	protected DateAttribute startDate_;
240 
241 	/**
242 	 * The end date of this key's validity.
243 	 */
244 	protected DateAttribute endDate_;
245 
246 	/**
247 	 * True, if other keys can be derived from this key.
248 	 */
249 	protected BooleanAttribute derive_;
250 
251 	/**
252 	 * True, if this key was created (generated or copied from a different key) on
253 	 * the token.
254 	 */
255 	protected BooleanAttribute local_;
256 
257 	/**
258 	 * The mechanism used to generate the key material.
259 	 */
260 	protected MechanismAttribute keyGenMechanism_;
261 
262 	/**
263 	 * The list of mechanism that can be used with this key.
264 	 */
265 	protected MechanismArrayAttribute allowedMechanisms_;
266 
267 	/**
268 	 * The default constructor. An application use this constructor to instanciate
269 	 * a key that serves as a template. It may also be useful for working with
270 	 * vendor-defined keys.
271 	 *
272 	 * @preconditions
273 	 * @postconditions
274 	 */
Key()275 	public Key() {
276 		super();
277 	}
278 
279 	/**
280 	 * Called by sub-classes to create an instance of a PKCS#11 key.
281 	 *
282 	 * @param session The session to use for reading attributes.
283 	 *                This session must have the appropriate rights; i.e.
284 	 *                it must be a user-session, if it is a private object.
285 	 * @param objectHandle The object handle as given from the PKCS#111 module.
286 	 * @exception TokenException If getting the attributes failed.
287 	 * @preconditions (session <> null)
288 	 * @postconditions
289 	 */
Key(Session session, long objectHandle)290 	protected Key(Session session, long objectHandle)
291 	    throws TokenException
292 	{
293 		super(session, objectHandle);
294 	}
295 
296 	/**
297 	 * Set a vendor-defined key builder that should be called to create an
298 	 * instance of an vendor-defined PKCS#11 key; i.e. an instance of a
299 	 * vendor defined sub-class of this class.
300 	 *
301 	 * @param builder The vendor-defined key builder. Null to clear any
302 	 *                previously installed vendor-defined builder.
303 	 * @preconditions
304 	 * @postconditions
305 	 */
setVendorDefinedKeyBuilder(VendorDefinedKeyBuilder builder)306 	public static void setVendorDefinedKeyBuilder(VendorDefinedKeyBuilder builder) {
307 		vendorKeyBuilder_ = builder;
308 	}
309 
310 	/**
311 	 * Get the currently set vendor-defined key builder.
312 	 *
313 	 * @return The currently set vendor-defined key builder or null if
314 	 *         none is set.
315 	 * @preconditions
316 	 * @postconditions
317 	 */
getVendorDefinedKeyBuilder()318 	public static VendorDefinedKeyBuilder getVendorDefinedKeyBuilder() {
319 		return vendorKeyBuilder_;
320 	}
321 
322 	/**
323 	 * Get the given key type as string.
324 	 *
325 	 * @param keyType The key type to get as string.
326 	 * @return A string denoting the key type; e.g. "RSA".
327 	 * @preconditions (keyType <> null)
328 	 * @postconditions (result <> null)
329 	 */
getKeyTypeName(Long keyType)330 	public static String getKeyTypeName(Long keyType) {
331 		String keyTypeName;
332 
333 		if (keyType == null) {
334 			throw new NullPointerException("Argument \"keyType\" must not be null.");
335 		}
336 
337 		if ((keyType.longValue() & PKCS11Constants.CKK_VENDOR_DEFINED) != 0L) {
338 			keyTypeName = "Vendor Defined";
339 		} else {
340 			if (keyTypeNames_ == null) {
341 				// setup key type names table
342 				Hashtable keyTypeNames = new Hashtable(24);
343 				keyTypeNames.put(KeyType.RSA, "RSA");
344 				keyTypeNames.put(KeyType.DSA, "DSA");
345 				keyTypeNames.put(KeyType.DH, "DH");
346 				keyTypeNames.put(KeyType.ECDSA, "ECDSA");
347 				keyTypeNames.put(KeyType.EC, "EC");
348 				keyTypeNames.put(KeyType.X9_42_DH, "X9_42_DH");
349 				keyTypeNames.put(KeyType.KEA, "KEA");
350 				keyTypeNames.put(KeyType.GENERIC_SECRET, "GENERIC_SECRET");
351 				keyTypeNames.put(KeyType.RC2, "RC2");
352 				keyTypeNames.put(KeyType.RC4, "RC4");
353 				keyTypeNames.put(KeyType.DES, "DES");
354 				keyTypeNames.put(KeyType.DES2, "DES2");
355 				keyTypeNames.put(KeyType.DES3, "DES3");
356 				keyTypeNames.put(KeyType.CAST, "CAST");
357 				keyTypeNames.put(KeyType.CAST3, "CAST3");
358 				keyTypeNames.put(KeyType.CAST5, "CAST5");
359 				keyTypeNames.put(KeyType.CAST128, "CAST128");
360 				keyTypeNames.put(KeyType.RC5, "RC5");
361 				keyTypeNames.put(KeyType.IDEA, "IDEA");
362 				keyTypeNames.put(KeyType.SKIPJACK, "SKIPJACK");
363 				keyTypeNames.put(KeyType.BATON, "BATON");
364 				keyTypeNames.put(KeyType.JUNIPER, "JUNIPER");
365 				keyTypeNames.put(KeyType.CDMF, "CDMF");
366 				keyTypeNames.put(KeyType.AES, "AES");
367 				keyTypeNames.put(KeyType.BLOWFISH, "BLOWFISH");
368 				keyTypeNames.put(KeyType.TWOFISH, "TWOFISH");
369 				keyTypeNames_ = keyTypeNames;
370 			}
371 
372 			keyTypeName = (String) keyTypeNames_.get(keyType);
373 			if (keyTypeName == null) {
374 				keyTypeName = "<unknown>";
375 			}
376 		}
377 
378 		return keyTypeName;
379 	}
380 
381 	/**
382 	 * Put all attributes of the given object into the attributes table of this
383 	 * object. This method is only static to be able to access invoke the
384 	 * implementation of this method for each class separately (see use in
385 	 * clone()).
386 	 *
387 	 * @param object The object to handle.
388 	 * @preconditions (object <> null)
389 	 * @postconditions
390 	 */
putAttributesInTable(Key object)391 	protected static void putAttributesInTable(Key object) {
392 		if (object == null) {
393 			throw new NullPointerException("Argument \"object\" must not be null.");
394 		}
395 
396 		object.attributeTable_.put(Attribute.KEY_TYPE, object.keyType_);
397 		object.attributeTable_.put(Attribute.ID, object.id_);
398 		object.attributeTable_.put(Attribute.START_DATE, object.startDate_);
399 		object.attributeTable_.put(Attribute.END_DATE, object.endDate_);
400 		object.attributeTable_.put(Attribute.DERIVE, object.derive_);
401 		object.attributeTable_.put(Attribute.LOCAL, object.local_);
402 		object.attributeTable_.put(Attribute.KEY_GEN_MECHANISM, object.keyGenMechanism_);
403 		object.attributeTable_.put(Attribute.ALLOWED_MECHANISMS, object.allowedMechanisms_);
404 	}
405 
406 	/**
407 	 * Allocates the attribute objects for this class and adds them to the
408 	 * attribute table.
409 	 *
410 	 * @preconditions
411 	 * @postconditions
412 	 */
allocateAttributes()413 	protected void allocateAttributes() {
414 		super.allocateAttributes();
415 
416 		keyType_ = new KeyTypeAttribute();
417 		id_ = new ByteArrayAttribute(Attribute.ID);
418 		startDate_ = new DateAttribute(Attribute.START_DATE);
419 		endDate_ = new DateAttribute(Attribute.END_DATE);
420 		derive_ = new BooleanAttribute(Attribute.DERIVE);
421 		local_ = new BooleanAttribute(Attribute.LOCAL);
422 		keyGenMechanism_ = new MechanismAttribute(Attribute.KEY_GEN_MECHANISM);
423 		allowedMechanisms_ = new MechanismArrayAttribute(Attribute.ALLOWED_MECHANISMS);
424 
425 		putAttributesInTable(this);
426 	}
427 
428 	/**
429 	 * Create a (deep) clone of this object.
430 	 *
431 	 * @return A clone of this object.
432 	 * @preconditions
433 	 * @postconditions (result <> null)
434 	 *                 and (result instanceof Key)
435 	 *                 and (result.equals(this))
436 	 */
clone()437 	public java.lang.Object clone() {
438 		Key clone = (Key) super.clone();
439 
440 		clone.keyType_ = (KeyTypeAttribute) this.keyType_.clone();
441 		clone.id_ = (ByteArrayAttribute) this.id_.clone();
442 		clone.startDate_ = (DateAttribute) this.startDate_.clone();
443 		clone.endDate_ = (DateAttribute) this.endDate_.clone();
444 		clone.derive_ = (BooleanAttribute) this.derive_.clone();
445 		clone.local_ = (BooleanAttribute) this.local_.clone();
446 		clone.keyGenMechanism_ = (MechanismAttribute) this.keyGenMechanism_.clone();
447 		clone.allowedMechanisms_ = (MechanismArrayAttribute) this.allowedMechanisms_.clone();
448 
449 		putAttributesInTable(clone); // put all cloned attributes into the new table
450 
451 		return clone;
452 	}
453 
454 	/**
455 	 * Compares all member variables of this object with the other object.
456 	 * Returns only true, if all are equal in both objects.
457 	 *
458 	 * @param otherObject The other object to compare to.
459 	 * @return True, if other is an instance of this class and all member
460 	 *         variables of both objects are equal. False, otherwise.
461 	 * @preconditions
462 	 * @postconditions
463 	 */
equals(java.lang.Object otherObject)464 	public boolean equals(java.lang.Object otherObject) {
465 		boolean equal = false;
466 
467 		if (otherObject instanceof Key) {
468 			Key other = (Key) otherObject;
469 			equal = (this == other)
470 			    || (super.equals(other) && this.keyType_.equals(other.keyType_)
471 			        && this.id_.equals(other.id_) && this.startDate_.equals(other.startDate_)
472 			        && this.endDate_.equals(other.endDate_)
473 			        && this.derive_.equals(other.derive_) && this.local_.equals(other.local_)
474 			        && this.keyGenMechanism_.equals(other.keyGenMechanism_) && this.allowedMechanisms_
475 			          .equals(other.allowedMechanisms_));
476 		}
477 
478 		return equal;
479 	}
480 
481 	/**
482 	 * Gets the key type attribute of the PKCS#11 key. Its value must
483 	 * be one of those defined in the KeyType interface or one with an
484 	 * value bigger than KeyType.VENDOR_DEFINED.
485 	 *
486 	 * @return The key type identifier.
487 	 * @preconditions
488 	 * @postconditions (result <> null)
489 	 */
getKeyType()490 	public LongAttribute getKeyType() {
491 		return keyType_;
492 	}
493 
494 	/**
495 	 * Gets the ID attribute of this key.
496 	 *
497 	 * @return The key identifier attribute.
498 	 * @preconditions
499 	 * @postconditions (result <> null)
500 	 */
getId()501 	public ByteArrayAttribute getId() {
502 		return id_;
503 	}
504 
505 	/**
506 	 * Gets the start date attribute of the validity of this key.
507 	 *
508 	 * @return The start date of validity.
509 	 * @preconditions
510 	 * @postconditions (result <> null)
511 	 */
getStartDate()512 	public DateAttribute getStartDate() {
513 		return startDate_;
514 	}
515 
516 	/**
517 	 * Gets the end date attribute of the validity of this key.
518 	 *
519 	 * @return The end date of validity.
520 	 * @preconditions
521 	 * @postconditions (result <> null)
522 	 */
getEndDate()523 	public DateAttribute getEndDate() {
524 		return endDate_;
525 	}
526 
527 	/**
528 	 * Check, if other keys can be derived from this key.
529 	 *
530 	 * @return Its value is true, if other keys can be derived from this key.
531 	 * @preconditions
532 	 * @postconditions (result <> null)
533 	 */
getDerive()534 	public BooleanAttribute getDerive() {
535 		return derive_;
536 	}
537 
538 	/**
539 	 * Check, if this key is a local key; i.e. was generated on the token or
540 	 * created via copy from a different key on the token.
541 	 *
542 	 * @return Its value is true, if the key was created on the token.
543 	 * @preconditions
544 	 * @postconditions (result <> null)
545 	 */
getLocal()546 	public BooleanAttribute getLocal() {
547 		return local_;
548 	}
549 
550 	/**
551 	 * Get the mechanism used to generate the key material for this key.
552 	 *
553 	 * @return The mechanism attribute used to generate the key material for this
554 	 *         key.
555 	 * @preconditions
556 	 * @postconditions (result <> null)
557 	 */
getKeyGenMechanism()558 	public MechanismAttribute getKeyGenMechanism() {
559 		return keyGenMechanism_;
560 	}
561 
562 	/**
563 	 * Get the list of mechanisms that are allowed to use with this key. This
564 	 * attribute can only be used with PKCS#11 modules supporting
565 	 * cryptoki version 2.20 or higher.
566 	 *
567 	 * @return The list of mechanisms that are allowed to use with this key.
568 	 * @preconditions
569 	 * @postconditions (result <> null)
570 	 */
getAllowedMechanisms()571 	public MechanismArrayAttribute getAllowedMechanisms() {
572 		return allowedMechanisms_;
573 	}
574 
575 	/**
576 	 * The overriding of this method should ensure that the objects of this class
577 	 * work correctly in a hashtable.
578 	 *
579 	 * @return The hash code of this object.
580 	 * @preconditions
581 	 * @postconditions
582 	 */
hashCode()583 	public int hashCode() {
584 		return keyType_.hashCode() ^ id_.hashCode();
585 	}
586 
587 	/**
588 	 * Read the values of the attributes of this object from the token.
589 	 *
590 	 * @param session The session handle to use for reading attributes.
591 	 *                This session must have the appropriate rights; i.e.
592 	 *                it must be a user-session, if it is a private object.
593 	 * @exception TokenException If getting the attributes failed.
594 	 * @preconditions (session <> null)
595 	 * @postconditions
596 	 */
readAttributes(Session session)597 	public void readAttributes(Session session)
598 	    throws TokenException
599 	{
600 		super.readAttributes(session);
601 
602 		//    Object.getAttributeValue(session, objectHandle_, id_);
603 		//    Object.getAttributeValue(session, objectHandle_, startDate_);
604 		//    Object.getAttributeValue(session, objectHandle_, endDate_);
605 		//    Object.getAttributeValue(session, objectHandle_, derive_);
606 		//    Object.getAttributeValue(session, objectHandle_, local_);
607 		//    Object.getAttributeValue(session, objectHandle_, keyGenMechanism_);
608 		Object.getAttributeValues(session, objectHandle_, new Attribute[] { id_, startDate_,
609 		    endDate_, derive_, local_, keyGenMechanism_ });
610 		Object.getAttributeValue(session, objectHandle_, allowedMechanisms_);
611 	}
612 
613 	/**
614 	 * This method returns a string representation of the current object. The
615 	 * output is only for debugging purposes and should not be used for other
616 	 * purposes.
617 	 *
618 	 * @return A string presentation of this object for debugging output.
619 	 * @preconditions
620 	 * @postconditions (result <> null)
621 	 */
toString()622 	public String toString() {
623 		StringBuffer buffer = new StringBuffer(256);
624 
625 		buffer.append(super.toString());
626 
627 		buffer.append(Constants.NEWLINE);
628 		buffer.append(Constants.INDENT);
629 		buffer.append("Key Type: ");
630 		if (keyType_ != null) {
631 			buffer.append(keyType_.toString());
632 		} else {
633 			buffer.append("<unavailable>");
634 		}
635 
636 		buffer.append(Constants.NEWLINE);
637 		buffer.append(Constants.INDENT);
638 		buffer.append("ID: ");
639 		buffer.append(id_.toString());
640 
641 		buffer.append(Constants.NEWLINE);
642 		buffer.append(Constants.INDENT);
643 		buffer.append("Start Date: ");
644 		buffer.append(startDate_.toString());
645 
646 		buffer.append(Constants.NEWLINE);
647 		buffer.append(Constants.INDENT);
648 		buffer.append("End Date: ");
649 		buffer.append(endDate_.toString());
650 
651 		buffer.append(Constants.NEWLINE);
652 		buffer.append(Constants.INDENT);
653 		buffer.append("Derive: ");
654 		buffer.append(derive_.toString());
655 
656 		buffer.append(Constants.NEWLINE);
657 		buffer.append(Constants.INDENT);
658 		buffer.append("Local: ");
659 		buffer.append(local_.toString());
660 
661 		buffer.append(Constants.NEWLINE);
662 		buffer.append(Constants.INDENT);
663 		buffer.append("Key Generation Mechanism: ");
664 		buffer.append(keyGenMechanism_.toString());
665 
666 		buffer.append(Constants.NEWLINE);
667 		buffer.append(Constants.INDENT);
668 		buffer.append("Allowed Mechanisms: ");
669 		buffer.append(allowedMechanisms_.toString());
670 
671 		return buffer.toString();
672 	}
673 
674 }
675