Path: blob/master/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java
41161 views
/*1* Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.security.auth.kerberos;2627import java.io.*;28import java.util.Arrays;29import javax.crypto.SecretKey;30import javax.security.auth.Destroyable;31import javax.security.auth.DestroyFailedException;32import sun.security.util.HexDumpEncoder;33import sun.security.krb5.Asn1Exception;34import sun.security.krb5.PrincipalName;35import sun.security.krb5.EncryptionKey;36import sun.security.krb5.EncryptedData;37import sun.security.krb5.KrbException;38import sun.security.util.DerValue;3940/**41* This class encapsulates a Kerberos encryption key. It is not associated42* with a principal and may represent an ephemeral session key.43*44* @author Mayank Upadhyay45* @since 1.446*47* @serial include48*/49class KeyImpl implements SecretKey, Destroyable, Serializable {5051private static final long serialVersionUID = -7889313790214321193L;5253private transient byte[] keyBytes;54private transient int keyType;55private transient volatile boolean destroyed = false;565758/**59* Constructs a KeyImpl from the given bytes.60*61* @param keyBytes the raw bytes for the secret key62* @param keyType the key type for the secret key as defined by the63* Kerberos protocol specification.64*/65public KeyImpl(byte[] keyBytes,66int keyType) {67this.keyBytes = keyBytes.clone();68this.keyType = keyType;69}7071/**72* Constructs a KeyImpl from a password.73*74* @param principal the principal from which to derive the salt75* @param password the password that should be used to compute the76* key.77* @param algorithm the name for the algorithm that this key wil be78* used for. This parameter may be null in which case "DES" will be79* assumed.80*/81public KeyImpl(KerberosPrincipal principal,82char[] password,83String algorithm) {8485try {86PrincipalName princ = new PrincipalName(principal.getName());87EncryptionKey key;88if ("none".equalsIgnoreCase(algorithm)) {89key = EncryptionKey.NULL_KEY;90} else {91key = new EncryptionKey(password, princ.getSalt(), algorithm);92}93this.keyBytes = key.getBytes();94this.keyType = key.getEType();95} catch (KrbException e) {96throw new IllegalArgumentException(e.getMessage());97}98}99100/**101* Returns the keyType for this key as defined in the Kerberos Spec.102*/103public final int getKeyType() {104if (destroyed)105throw new IllegalStateException("This key is no longer valid");106return keyType;107}108109/*110* Methods from java.security.Key111*/112113public final String getAlgorithm() {114return getAlgorithmName(keyType);115}116117private String getAlgorithmName(int eType) {118if (destroyed)119throw new IllegalStateException("This key is no longer valid");120121switch (eType) {122case EncryptedData.ETYPE_DES_CBC_CRC:123return "des-cbc-crc";124125case EncryptedData.ETYPE_DES_CBC_MD5:126return "des-cbc-md5";127128case EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD:129return "des3-cbc-sha1-kd";130131case EncryptedData.ETYPE_ARCFOUR_HMAC:132return "rc4-hmac";133134case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA1_96:135return "aes128-cts-hmac-sha1-96";136137case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA1_96:138return "aes256-cts-hmac-sha1-96";139140case EncryptedData.ETYPE_AES128_CTS_HMAC_SHA256_128:141return "aes128-cts-hmac-sha256-128";142143case EncryptedData.ETYPE_AES256_CTS_HMAC_SHA384_192:144return "aes256-cts-hmac-sha384-192";145146case EncryptedData.ETYPE_NULL:147return "none";148149default:150return eType > 0 ? "unknown" : "private";151}152}153154public final String getFormat() {155if (destroyed)156throw new IllegalStateException("This key is no longer valid");157return "RAW";158}159160public final byte[] getEncoded() {161if (destroyed)162throw new IllegalStateException("This key is no longer valid");163return keyBytes.clone();164}165166public void destroy() throws DestroyFailedException {167if (!destroyed) {168destroyed = true;169Arrays.fill(keyBytes, (byte) 0);170}171}172173public boolean isDestroyed() {174return destroyed;175}176177/**178* Writes the state of this object to the stream.179180* @serialData this {@code KeyImpl} is serialized by181* writing out the ASN.1 Encoded bytes of the encryption key.182* The ASN.1 encoding is defined in RFC4120 as follows:183* EncryptionKey ::= SEQUENCE {184* keytype [0] Int32 -- actually encryption type --,185* keyvalue [1] OCTET STRING186*187* @param oos the {@code ObjectOutputStream} to which data is written188* @throws IOException if an I/O error occurs189* }190*/191private void writeObject(ObjectOutputStream oos)192throws IOException {193if (destroyed) {194throw new IOException("This key is no longer valid");195}196197try {198oos.writeObject((new EncryptionKey(keyType, keyBytes)).asn1Encode());199} catch (Asn1Exception ae) {200throw new IOException(ae.getMessage());201}202}203204/**205* Restores the state of this object from the stream.206*207* @param ois the {@code ObjectInputStream} from which data is read208* @throws IOException if an I/O error occurs209* @throws ClassNotFoundException if a serialized class cannot be loaded210*/211private void readObject(ObjectInputStream ois)212throws IOException, ClassNotFoundException {213try {214EncryptionKey encKey = new EncryptionKey(new215DerValue((byte[])ois.readObject()));216keyType = encKey.getEType();217keyBytes = encKey.getBytes();218} catch (Asn1Exception ae) {219throw new IOException(ae.getMessage());220}221}222223public String toString() {224HexDumpEncoder hd = new HexDumpEncoder();225return "EncryptionKey: keyType=" + keyType226+ " keyBytes (hex dump)="227+ (keyBytes == null || keyBytes.length == 0 ?228" Empty Key" :229'\n' + hd.encodeBuffer(keyBytes)230+ '\n');231232233}234235public int hashCode() {236int result = 17;237if(isDestroyed()) {238return result;239}240result = 37 * result + Arrays.hashCode(keyBytes);241return 37 * result + keyType;242}243244public boolean equals(Object other) {245246if (other == this)247return true;248249if (! (other instanceof KeyImpl)) {250return false;251}252253KeyImpl otherKey = ((KeyImpl) other);254if (isDestroyed() || otherKey.isDestroyed()) {255return false;256}257258if(keyType != otherKey.getKeyType() ||259!Arrays.equals(keyBytes, otherKey.getEncoded())) {260return false;261}262263return true;264}265}266267268