blob: 9baa065cc8f13c6fc4b3100eee936964ad0964bd [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26package javax.security.auth.kerberos;
27
28import java.util.Arrays;
29import javax.crypto.SecretKey;
30import javax.security.auth.Destroyable;
31import javax.security.auth.DestroyFailedException;
32
33/**
34 * This class encapsulates a long term secret key for a Kerberos
35 * principal.<p>
36 *
37 * All Kerberos JAAS login modules that obtain a principal's password and
38 * generate the secret key from it should use this class. Where available,
39 * the login module might even read this secret key directly from a
40 * Kerberos "keytab". Sometimes, such as when authenticating a server in
41 * the absence of user-to-user authentication, the login module will store
42 * an instance of this class in the private credential set of a
43 * {@link javax.security.auth.Subject Subject} during the commit phase of the
44 * authentication process.<p>
45 *
46 * It might be necessary for the application to be granted a
47 * {@link javax.security.auth.PrivateCredentialPermission
48 * PrivateCredentialPermission} if it needs to access the KerberosKey
49 * instance from a Subject. This permission is not needed when the
50 * application depends on the default JGSS Kerberos mechanism to access the
51 * KerberosKey. In that case, however, the application will need an
52 * appropriate
53 * {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
54 *
55 * @author Mayank Upadhyay
56 * @since 1.4
57 */
58public class KerberosKey implements SecretKey, Destroyable {
59
60 private static final long serialVersionUID = -4625402278148246993L;
61
62 /**
63 * The principal that this secret key belongs to.
64 *
65 * @serial
66 */
67 private KerberosPrincipal principal;
68
69 /**
70 * the version number of this secret key
71 *
72 * @serial
73 */
74 private int versionNum;
75
76 /**
77 * <code>KeyImpl</code> is serialized by writing out the ASN1 Encoded bytes
78 * of the encryption key.
79 * The ASN1 encoding is defined in RFC4120 and as follows:
80 * <pre>
81 * EncryptionKey ::= SEQUENCE {
82 * keytype [0] Int32 -- actually encryption type --,
83 * keyvalue [1] OCTET STRING
84 * }
85 * </pre>
86 *
87 * @serial
88 */
89
90 private KeyImpl key;
91 private transient boolean destroyed = false;
92
93 /**
94 * Constructs a KerberosKey from the given bytes when the key type and
95 * key version number are known. This can be used when reading the secret
96 * key information from a Kerberos "keytab".
97 *
98 * @param principal the principal that this secret key belongs to
99 * @param keyBytes the raw bytes for the secret key
100 * @param keyType the key type for the secret key as defined by the
101 * Kerberos protocol specification.
102 * @param versionNum the version number of this secret key
103 */
104 public KerberosKey(KerberosPrincipal principal,
105 byte[] keyBytes,
106 int keyType,
107 int versionNum) {
108 this.principal = principal;
109 this.versionNum = versionNum;
110 key = new KeyImpl(keyBytes, keyType);
111 }
112
113 /**
114 * Constructs a KerberosKey from a principal's password.
115 *
116 * @param principal the principal that this password belongs to
117 * @param password the password that should be used to compute the key
118 * @param algorithm the name for the algorithm that this key will be
119 * used for. This parameter may be null in which case the default
120 * algorithm "DES" will be assumed.
121 * @throws IllegalArgumentException if the name of the
122 * algorithm passed is unsupported.
123 */
124 public KerberosKey(KerberosPrincipal principal,
125 char[] password,
126 String algorithm) {
127
128 this.principal = principal;
129 // Pass principal in for salt
130 key = new KeyImpl(principal, password, algorithm);
131 }
132
133 /**
134 * Returns the principal that this key belongs to.
135 *
136 * @return the principal this key belongs to.
137 */
138 public final KerberosPrincipal getPrincipal() {
139 if (destroyed)
140 throw new IllegalStateException("This key is no longer valid");
141 return principal;
142 }
143
144 /**
145 * Returns the key version number.
146 *
147 * @return the key version number.
148 */
149 public final int getVersionNumber() {
150 if (destroyed)
151 throw new IllegalStateException("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("This key is no longer valid");
163 return key.getKeyType();
164 }
165
166 /*
167 * Methods from java.security.Key
168 */
169
170 /**
171 * Returns the standard algorithm name for this key. For
172 * example, "DES" would indicate that this key is a DES key.
173 * See Appendix A in the <a href=
174 * "../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
175 * Java Cryptography Architecture API Specification &amp; Reference
176 * </a>
177 * for information about standard algorithm names.
178 *
179 * @return the name of the algorithm associated with this key.
180 */
181 public final String getAlgorithm() {
182 if (destroyed)
183 throw new IllegalStateException("This key is no longer valid");
184 return key.getAlgorithm();
185 }
186
187 /**
188 * Returns the name of the encoding format for this secret key.
189 *
190 * @return the String "RAW"
191 */
192 public final String getFormat() {
193 if (destroyed)
194 throw new IllegalStateException("This key is no longer valid");
195 return key.getFormat();
196 }
197
198 /**
199 * Returns the key material of this secret key.
200 *
201 * @return the key material
202 */
203 public final byte[] getEncoded() {
204 if (destroyed)
205 throw new IllegalStateException("This key is no longer valid");
206 return key.getEncoded();
207 }
208
209 /**
210 * Destroys this key. A call to any of its other methods after this
211 * will cause an IllegalStateException to be thrown.
212 *
213 * @throws DestroyFailedException if some error occurs while destorying
214 * this key.
215 */
216 public void destroy() throws DestroyFailedException {
217 if (!destroyed) {
218 key.destroy();
219 principal = null;
220 destroyed = true;
221 }
222 }
223
224
225 /** Determines if this key has been destroyed.*/
226 public boolean isDestroyed() {
227 return destroyed;
228 }
229
230 public String toString() {
231 if (destroyed) {
232 return "Destroyed Principal";
233 }
234 return "Kerberos Principal " + principal.toString() +
235 "Key Version " + versionNum +
236 "key " + key.toString();
237 }
238
239 /**
240 * Returns a hashcode for this KerberosKey.
241 *
242 * @return a hashCode() for the <code>KerberosKey</code>
243 * @since 1.6
244 */
245 public int hashCode() {
246 int result = 17;
247 if (isDestroyed()) {
248 return result;
249 }
250 result = 37 * result + Arrays.hashCode(getEncoded());
251 result = 37 * result + getKeyType();
252 if (principal != null) {
253 result = 37 * result + principal.hashCode();
254 }
255 return result * 37 + versionNum;
256 }
257
258 /**
259 * Compares the specified Object with this KerberosKey for equality.
260 * Returns true if the given object is also a
261 * <code>KerberosKey</code> and the two
262 * <code>KerberosKey</code> instances are equivalent.
263 *
264 * @param other the Object to compare to
265 * @return true if the specified object is equal to this KerberosKey,
266 * false otherwise. NOTE: Returns false if either of the KerberosKey
267 * objects has been destroyed.
268 * @since 1.6
269 */
270 public boolean equals(Object other) {
271
272 if (other == this)
273 return true;
274
275 if (! (other instanceof KerberosKey)) {
276 return false;
277 }
278
279 KerberosKey otherKey = ((KerberosKey) other);
280 if (isDestroyed() || otherKey.isDestroyed()) {
281 return false;
282 }
283
284 if (versionNum != otherKey.getVersionNumber() ||
285 getKeyType() != otherKey.getKeyType() ||
286 !Arrays.equals(getEncoded(), otherKey.getEncoded())) {
287 return false;
288 }
289
290 if (principal == null) {
291 if (otherKey.getPrincipal() != null) {
292 return false;
293 }
294 } else {
295 if (!principal.equals(otherKey.getPrincipal())) {
296 return false;
297 }
298 }
299
300 return true;
301 }
302}