You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
305 lines
8.7 KiB
305 lines
8.7 KiB
/*
|
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
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.
|
|
* 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>
|
|
*
|
|
* A Kerberos service using a keytab to read secret keys should use
|
|
* the {@link KeyTab} class, where latest keys can be read when needed.<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} 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 & 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}
|
|
* @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} and the two
|
|
* {@code KerberosKey} 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;
|
|
}
|
|
}
|