Use Tree Navigation
public class

KerberosKey

extends Object
implements SecretKey Destroyable
/*
 * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */


package javax.security.auth.kerberos;

import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.security.auth.Destroyable;
import javax.security.auth.DestroyFailedException;

/**
 * This class encapsulates a long term secret key for a Kerberos
 * principal.<p>
 *
 * All Kerberos JAAS login modules that obtain a principal's password and
 * generate the secret key from it should use this class. Where available,
 * the login module might even read this secret key directly from a
 * Kerberos "keytab". Sometimes, such as when authenticating a server in
 * the absence of user-to-user authentication, the login module will store
 * an instance of this class in the private credential set of a
 * {@link javax.security.auth.Subject Subject} during the commit phase of the
 * authentication process.<p>
 *
 * It might be necessary for the application to be granted a
 * {@link javax.security.auth.PrivateCredentialPermission
 * PrivateCredentialPermission} if it needs to access the KerberosKey
 * instance from a Subject. This permission is not needed when the
 * application depends on the default JGSS Kerberos mechanism to access the
 * KerberosKey. In that case, however, the application will need an
 * appropriate
 * {@link javax.security.auth.kerberos.ServicePermission ServicePermission}.
 *
 * @author Mayank Upadhyay
 * @since 1.4
 */

public class KerberosKey implements SecretKey, Destroyable {

   
private static final long serialVersionUID = -4625402278148246993L;

   
/**
     * The principal that this secret key belongs to.
     *
     * @serial
     */

   
private KerberosPrincipal principal;

   
/**
     * the version number of this secret key
     *
     * @serial
     */

   
private int versionNum;

   
/**
    * <code>KeyImpl</code> is serialized by writing out the ASN1 Encoded bytes
    * of the encryption key.
    * The ASN1 encoding is defined in RFC4120 and as  follows:
    * <pre>
    * EncryptionKey   ::= SEQUENCE {
    *           keytype   [0] Int32 -- actually encryption type --,
    *           keyvalue  [1] OCTET STRING
    * }
    * </pre>
    *
    * @serial
    */


   
private KeyImpl key;
   
private transient boolean destroyed = false;

   
/**
     * Constructs a KerberosKey from the given bytes when the key type and
     * key version number are known. This can be used when reading the secret
     * key information from a Kerberos "keytab".
     *
     * @param principal the principal that this secret key belongs to
     * @param keyBytes the raw bytes for the secret key
     * @param keyType the key type for the secret key as defined by the
     * Kerberos protocol specification.
     * @param versionNum the version number of this secret key
     */

   
public KerberosKey(KerberosPrincipal principal,
                       
byte[] keyBytes,
                       
int keyType,
                       
int versionNum) {
       
this.principal = principal;
       
this.versionNum = versionNum;
        key
= new KeyImpl(keyBytes, keyType);
   
}

   
/**
     * Constructs a KerberosKey from a principal's password.
     *
     * @param principal the principal that this password belongs to
     * @param password the password that should be used to compute the key
     * @param algorithm the name for the algorithm that this key will be
     * used for. This parameter may be null in which case the default
     * algorithm "DES" will be assumed.
     * @throws IllegalArgumentException if the name of the
     * algorithm passed is unsupported.
     */

   
public KerberosKey(KerberosPrincipal principal,
                       
char[] password,
                       
String algorithm) {

       
this.principal = principal;
       
// Pass principal in for salt
        key
= new KeyImpl(principal, password, algorithm);
   
}

   
/**
     * Returns the principal that this key belongs to.
     *
     * @return the principal this key belongs to.
     */

   
public final KerberosPrincipal getPrincipal() {
       
if (destroyed)
           
throw new IllegalStateException("This key is no longer valid");
       
return principal;
   
}

   
/**
     * Returns the key version number.
     *
     * @return the key version number.
     */

   
public final int getVersionNumber() {
       
if (destroyed)
           
throw new IllegalStateException("This key is no longer valid");
       
return versionNum;
   
}

   
/**
     * Returns the key type for this long-term key.
     *
     * @return the key type.
     */

   
public final int getKeyType() {
       
if (destroyed)
           
throw new IllegalStateException("This key is no longer valid");
       
return key.getKeyType();
   
}

   
/*
     * Methods from java.security.Key
     */


   
/**
     * Returns the standard algorithm name for this key. For
     * example, "DES" would indicate that this key is a DES key.
     * See Appendix A in the <a href=
     * "../../../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
     * Java Cryptography Architecture API Specification &amp; Reference
     * </a>
     * for information about standard algorithm names.
     *
     * @return the name of the algorithm associated with this key.
     */

   
public final String getAlgorithm() {
       
if (destroyed)
           
throw new IllegalStateException("This key is no longer valid");
       
return key.getAlgorithm();
   
}

   
/**
     * Returns the name of the encoding format for this secret key.
     *
     * @return the String "RAW"
     */

   
public final String getFormat() {
       
if (destroyed)
           
throw new IllegalStateException("This key is no longer valid");
       
return key.getFormat();
   
}

   
/**
     * Returns the key material of this secret key.
     *
     * @return the key material
     */

   
public final byte[] getEncoded() {
       
if (destroyed)
           
throw new IllegalStateException("This key is no longer valid");
       
return key.getEncoded();
   
}

   
/**
     * Destroys this key. A call to any of its other methods after this
     * will cause an  IllegalStateException to be thrown.
     *
     * @throws DestroyFailedException if some error occurs while destorying
     * this key.
     */

   
public void destroy() throws DestroyFailedException {
       
if (!destroyed) {
            key
.destroy();
            principal
= null;
            destroyed
= true;
       
}
   
}


   
/** Determines if this key has been destroyed.*/
   
public boolean isDestroyed() {
       
return destroyed;
   
}

   
public String toString() {
       
if (destroyed) {
           
return "Destroyed Principal";
       
}
       
return "Kerberos Principal " + principal.toString() +
               
"Key Version " + versionNum +
               
"key "  + key.toString();
   
}

   
/**
     * Returns a hashcode for this KerberosKey.
     *
     * @return a hashCode() for the <code>KerberosKey</code>
     * @since 1.6
     */

   
public int hashCode() {
       
int result = 17;
       
if (isDestroyed()) {
           
return result;
       
}
        result
= 37 * result + Arrays.hashCode(getEncoded());
        result
= 37 * result + getKeyType();
       
if (principal != null) {
            result
= 37 * result + principal.hashCode();
       
}
       
return result * 37 + versionNum;
   
}

   
/**
     * Compares the specified Object with this KerberosKey for equality.
     * Returns true if the given object is also a
     * <code>KerberosKey</code> and the two
     * <code>KerberosKey</code> instances are equivalent.
     *
     * @param other the Object to compare to
     * @return true if the specified object is equal to this KerberosKey,
     * false otherwise. NOTE: Returns false if either of the KerberosKey
     * objects has been destroyed.
     * @since 1.6
     */

   
public boolean equals(Object other) {

       
if (other == this)
           
return true;

       
if (! (other instanceof KerberosKey)) {
           
return false;
       
}

       
KerberosKey otherKey = ((KerberosKey) other);
       
if (isDestroyed() || otherKey.isDestroyed()) {
           
return false;
       
}

       
if (versionNum != otherKey.getVersionNumber() ||
                getKeyType
() != otherKey.getKeyType() ||
               
!Arrays.equals(getEncoded(), otherKey.getEncoded())) {
           
return false;
       
}

       
if (principal == null) {
           
if (otherKey.getPrincipal() != null) {
               
return false;
           
}
       
} else {
           
if (!principal.equals(otherKey.getPrincipal())) {
               
return false;
           
}
       
}

       
return true;
   
}
}