1. /*
  2. * @(#)KeyImpl.java 1.9 03/01/23
  3. *
  4. * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.security.auth.kerberos;
  8. import java.io.*;
  9. import java.util.Arrays;
  10. import javax.crypto.SecretKey;
  11. import javax.security.auth.Destroyable;
  12. import javax.security.auth.DestroyFailedException;
  13. import sun.misc.HexDumpEncoder;
  14. import sun.security.krb5.Asn1Exception;
  15. import sun.security.krb5.PrincipalName;
  16. import sun.security.krb5.EncryptionKey;
  17. import sun.security.krb5.EncryptedData;
  18. import sun.security.krb5.KrbException;
  19. import sun.security.krb5.KrbCryptoException;
  20. import sun.security.util.DerValue;
  21. /**
  22. * This class encapsulates a Kerberos encryption key. It is not associated
  23. * with a principal and may represent an ephemeral session key.
  24. *
  25. * @author Mayank Upadhyay
  26. * @version 1.9, 01/23/03
  27. * @since 1.4
  28. */
  29. class KeyImpl implements SecretKey, Destroyable, Serializable {
  30. private transient byte[] keyBytes;
  31. private transient int keyType;
  32. private transient boolean destroyed = false;
  33. /**
  34. * Constructs a KeyImpl from the given bytes.
  35. *
  36. * @param keyBytes the raw bytes for the secret key
  37. * @param keyType the key type for the secret key as defined by the
  38. * Kerberos protocol specification.
  39. */
  40. public KeyImpl(byte[] keyBytes,
  41. int keyType) {
  42. this.keyBytes = (byte[]) keyBytes.clone();
  43. this.keyType = keyType;
  44. }
  45. /**
  46. * Constructs a KeyImpl from a password.
  47. *
  48. * @param principal the principal from which to derive the salt
  49. * @param password the password that should be used to compute the
  50. * key.
  51. * @param algorithm the name for the algorithm that this key wil be
  52. * used for. This parameter may be null in which case "DES" will be
  53. * assumed.
  54. */
  55. public KeyImpl(KerberosPrincipal principal,
  56. char[] password,
  57. String algorithm) {
  58. try {
  59. PrincipalName princ = new PrincipalName(principal.getName());
  60. EncryptionKey key =
  61. new EncryptionKey(new StringBuffer().append(password),
  62. princ.getSalt(),algorithm);
  63. this.keyBytes = key.getBytes();
  64. this.keyType = key.getEType();
  65. } catch (KrbException e) {
  66. throw new IllegalArgumentException(e.getMessage());
  67. }
  68. }
  69. /**
  70. * Returns the keyType for this key as defined in the Kerberos Spec.
  71. */
  72. public final int getKeyType() {
  73. if (destroyed)
  74. throw new IllegalStateException("This key is no longer valid");
  75. return keyType;
  76. }
  77. /*
  78. * Methods from java.security.Key
  79. */
  80. public final String getAlgorithm() {
  81. return getAlgorithmName(keyType);
  82. }
  83. private String getAlgorithmName(int eType) {
  84. if (destroyed)
  85. throw new IllegalStateException("This key is no longer valid");
  86. if (eType == EncryptedData.ETYPE_NULL)
  87. return "NULL";
  88. else
  89. // if (eType == ETYPE_DES_CBC_CRC ||
  90. // eType == ETYPE_DES_CBC_MD5)
  91. return "DES";
  92. }
  93. public final String getFormat() {
  94. if (destroyed)
  95. throw new IllegalStateException("This key is no longer valid");
  96. return "RAW";
  97. }
  98. public final byte[] getEncoded() {
  99. if (destroyed)
  100. throw new IllegalStateException("This key is no longer valid");
  101. return (byte[])keyBytes.clone();
  102. }
  103. public void destroy() throws DestroyFailedException {
  104. if (!destroyed) {
  105. Arrays.fill(keyBytes, (byte) 0);
  106. destroyed = true;
  107. }
  108. }
  109. public boolean isDestroyed() {
  110. return destroyed;
  111. }
  112. /**
  113. * @serialData this <code>KeyImpl</code> is serialized by
  114. * writing out the ASN1 Encoded bytes of the
  115. * encryption key. The ASN1 encoding is defined in
  116. * RFC1510 and as follows:
  117. * EncryptionKey ::= SEQUENCE {
  118. * keytype[0] INTEGER,
  119. * keyvalue[1] OCTET STRING
  120. * }
  121. **/
  122. private synchronized void writeObject(ObjectOutputStream ois)
  123. throws IOException {
  124. if (destroyed) {
  125. throw new IOException ("This key is no longer valid");
  126. }
  127. try {
  128. ois.writeObject((new EncryptionKey(keyType,keyBytes)).asn1Encode());
  129. } catch (Asn1Exception ae) {
  130. throw new IOException(ae.getMessage());
  131. }
  132. }
  133. private synchronized void readObject(ObjectInputStream ois)
  134. throws IOException , ClassNotFoundException {
  135. try {
  136. EncryptionKey encKey = new EncryptionKey(new
  137. DerValue((byte[])ois.readObject()));
  138. keyType = encKey.getEType();
  139. keyBytes = encKey.getBytes();
  140. } catch (Asn1Exception ae) {
  141. throw new IOException (ae.getMessage());
  142. }
  143. }
  144. public String toString() {
  145. HexDumpEncoder hd = new HexDumpEncoder();
  146. return new String("EncryptionKey: keyType=" + keyType
  147. + " keyBytes (hex dump)="
  148. + (keyBytes == null || keyBytes.length == 0 ?
  149. " Empty Key" :
  150. '\n' + hd.encode(keyBytes)
  151. + '\n'));
  152. }
  153. }