001 /*
002 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.security.auth.kerberos;
027
028 import java.util.Arrays;
029 import javax.crypto.SecretKey;
030 import javax.security.auth.Destroyable;
031 import javax.security.auth.DestroyFailedException;
032
033 /**
034 * This class encapsulates a long term secret key for a Kerberos
035 * principal.<p>
036 *
037 * All Kerberos JAAS login modules that obtain a principal's password and
038 * generate the secret key from it should use this class. Where available,
039 * the login module might even read this secret key directly from a
040 * Kerberos "keytab". Sometimes, such as when authenticating a server in
041 * the absence of user-to-user authentication, the login module will store
042 * an instance of this class in the private credential set of a
043 * {@link javax.security.auth.Subject Subject} during the commit phase of the
044 * authentication process.<p>
045 *
046 * It might be necessary for the application to be granted a
047 * {@link javax.security.auth.PrivateCredentialPermission
048 * PrivateCredentialPermission} if it needs to access the KerberosKey
049 * instance from a Subject. This permission is not needed when the
050 * application depends on the default JGSS Kerberos mechanism to access the
051 * KerberosKey. In that case, however, the application will need an
052 * appropriate
053 * {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
054 *
055 * @author Mayank Upadhyay
056 * @version 1.27, 05/05/07
057 * @since 1.4
058 */
059 public class KerberosKey implements SecretKey, Destroyable {
060
061 private static final long serialVersionUID = -4625402278148246993L;
062
063 /**
064 * The principal that this secret key belongs to.
065 *
066 * @serial
067 */
068 private KerberosPrincipal principal;
069
070 /**
071 * the version number of this secret key
072 *
073 * @serial
074 */
075 private int versionNum;
076
077 /**
078 * <code>KeyImpl</code> is serialized by writing out the ASN1 Encoded bytes
079 * of the encryption key.
080 * The ASN1 encoding is defined in RFC4120 and as follows:
081 * <pre>
082 * EncryptionKey ::= SEQUENCE {
083 * keytype [0] Int32 -- actually encryption type --,
084 * keyvalue [1] OCTET STRING
085 * }
086 * </pre>
087 *
088 * @serial
089 */
090
091 private KeyImpl key;
092 private transient boolean destroyed = false;
093
094 /**
095 * Constructs a KerberosKey from the given bytes when the key type and
096 * key version number are known. This can be used when reading the secret
097 * key information from a Kerberos "keytab".
098 *
099 * @param principal the principal that this secret key belongs to
100 * @param keyBytes the raw bytes for the secret key
101 * @param keyType the key type for the secret key as defined by the
102 * Kerberos protocol specification.
103 * @param versionNum the version number of this secret key
104 */
105 public KerberosKey(KerberosPrincipal principal, byte[] keyBytes,
106 int keyType, int versionNum) {
107 this .principal = principal;
108 this .versionNum = versionNum;
109 key = new KeyImpl(keyBytes, keyType);
110 }
111
112 /**
113 * Constructs a KerberosKey from a principal's password.
114 *
115 * @param principal the principal that this password belongs to
116 * @param password the password that should be used to compute the key
117 * @param algorithm the name for the algorithm that this key will be
118 * used for. This parameter may be null in which case the default
119 * algorithm "DES" will be assumed.
120 * @throws IllegalArgumentException if the name of the
121 * algorithm passed is unsupported.
122 */
123 public KerberosKey(KerberosPrincipal principal, char[] password,
124 String algorithm) {
125
126 this .principal = principal;
127 // Pass principal in for salt
128 key = new KeyImpl(principal, password, algorithm);
129 }
130
131 /**
132 * Returns the principal that this key belongs to.
133 *
134 * @return the principal this key belongs to.
135 */
136 public final KerberosPrincipal getPrincipal() {
137 if (destroyed)
138 throw new IllegalStateException(
139 "This key is no longer valid");
140 return principal;
141 }
142
143 /**
144 * Returns the key version number.
145 *
146 * @return the key version number.
147 */
148 public final int getVersionNumber() {
149 if (destroyed)
150 throw new IllegalStateException(
151 "This key is no longer valid");
152 return versionNum;
153 }
154
155 /**
156 * Returns the key type for this long-term key.
157 *
158 * @return the key type.
159 */
160 public final int getKeyType() {
161 if (destroyed)
162 throw new IllegalStateException(
163 "This key is no longer valid");
164 return key.getKeyType();
165 }
166
167 /*
168 * Methods from java.security.Key
169 */
170
171 /**
172 * Returns the standard algorithm name for this key. For
173 * example, "DES" would indicate that this key is a DES key.
174 * See Appendix A in the <a href=
175 * "../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
176 * Java Cryptography Architecture API Specification & Reference
177 * </a>
178 * for information about standard algorithm names.
179 *
180 * @return the name of the algorithm associated with this key.
181 */
182 public final String getAlgorithm() {
183 if (destroyed)
184 throw new IllegalStateException(
185 "This key is no longer valid");
186 return key.getAlgorithm();
187 }
188
189 /**
190 * Returns the name of the encoding format for this secret key.
191 *
192 * @return the String "RAW"
193 */
194 public final String getFormat() {
195 if (destroyed)
196 throw new IllegalStateException(
197 "This key is no longer valid");
198 return key.getFormat();
199 }
200
201 /**
202 * Returns the key material of this secret key.
203 *
204 * @return the key material
205 */
206 public final byte[] getEncoded() {
207 if (destroyed)
208 throw new IllegalStateException(
209 "This key is no longer valid");
210 return key.getEncoded();
211 }
212
213 /**
214 * Destroys this key. A call to any of its other methods after this
215 * will cause an IllegalStateException to be thrown.
216 *
217 * @throws DestroyFailedException if some error occurs while destorying
218 * this key.
219 */
220 public void destroy() throws DestroyFailedException {
221 if (!destroyed) {
222 key.destroy();
223 principal = null;
224 destroyed = true;
225 }
226 }
227
228 /** Determines if this key has been destroyed.*/
229 public boolean isDestroyed() {
230 return destroyed;
231 }
232
233 public String toString() {
234 if (destroyed) {
235 return "Destroyed Principal";
236 }
237 return "Kerberos Principal " + principal.toString()
238 + "Key Version " + versionNum + "key " + key.toString();
239 }
240
241 /**
242 * Returns a hashcode for this KerberosKey.
243 *
244 * @return a hashCode() for the <code>KerberosKey</code>
245 * @since 1.6
246 */
247 public int hashCode() {
248 int result = 17;
249 if (isDestroyed()) {
250 return result;
251 }
252 result = 37 * result + Arrays.hashCode(getEncoded());
253 result = 37 * result + getKeyType();
254 if (principal != null) {
255 result = 37 * result + principal.hashCode();
256 }
257 return result * 37 + versionNum;
258 }
259
260 /**
261 * Compares the specified Object with this KerberosKey for equality.
262 * Returns true if the given object is also a
263 * <code>KerberosKey</code> and the two
264 * <code>KerberosKey</code> instances are equivalent.
265 *
266 * @param other the Object to compare to
267 * @return true if the specified object is equal to this KerberosKey,
268 * false otherwise. NOTE: Returns false if either of the KerberosKey
269 * objects has been destroyed.
270 * @since 1.6
271 */
272 public boolean equals(Object other) {
273
274 if (other == this )
275 return true;
276
277 if (!(other instanceof KerberosKey)) {
278 return false;
279 }
280
281 KerberosKey otherKey = ((KerberosKey) other);
282 if (isDestroyed() || otherKey.isDestroyed()) {
283 return false;
284 }
285
286 if (versionNum != otherKey.getVersionNumber()
287 || getKeyType() != otherKey.getKeyType()
288 || !Arrays.equals(getEncoded(), otherKey.getEncoded())) {
289 return false;
290 }
291
292 if (principal == null) {
293 if (otherKey.getPrincipal() != null) {
294 return false;
295 }
296 } else {
297 if (!principal.equals(otherKey.getPrincipal())) {
298 return false;
299 }
300 }
301
302 return true;
303 }
304 }
|