1/* 2 * Copyright (c) 1997, 2017, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.crypto.provider; 27 28import java.security.MessageDigest; 29import java.security.KeyRep; 30import java.security.InvalidKeyException; 31import javax.crypto.SecretKey; 32import javax.crypto.spec.DESKeySpec; 33 34import jdk.internal.ref.CleanerFactory; 35 36/** 37 * This class represents a DES key. 38 * 39 * @author Jan Luehe 40 * 41 */ 42 43final class DESKey implements SecretKey { 44 45 static final long serialVersionUID = 7724971015953279128L; 46 47 private byte[] key; 48 49 /** 50 * Uses the first 8 bytes of the given key as the DES key. 51 * 52 * @param key the buffer with the DES key bytes. 53 * 54 * @exception InvalidKeyException if less than 8 bytes are available for 55 * the key. 56 */ 57 DESKey(byte[] key) throws InvalidKeyException { 58 this(key, 0); 59 } 60 61 /** 62 * Uses the first 8 bytes in <code>key</code>, beginning at 63 * <code>offset</code>, as the DES key 64 * 65 * @param key the buffer with the DES key bytes. 66 * @param offset the offset in <code>key</code>, where the DES key bytes 67 * start. 68 * 69 * @exception InvalidKeyException if less than 8 bytes are available for 70 * the key. 71 */ 72 DESKey(byte[] key, int offset) throws InvalidKeyException { 73 if (key == null || key.length - offset < DESKeySpec.DES_KEY_LEN) { 74 throw new InvalidKeyException("Wrong key size"); 75 } 76 this.key = new byte[DESKeySpec.DES_KEY_LEN]; 77 System.arraycopy(key, offset, this.key, 0, DESKeySpec.DES_KEY_LEN); 78 DESKeyGenerator.setParityBit(this.key, 0); 79 80 // Use the cleaner to zero the key when no longer referenced 81 final byte[] k = this.key; 82 CleanerFactory.cleaner().register(this, 83 () -> java.util.Arrays.fill(k, (byte)0x00)); 84 } 85 86 public byte[] getEncoded() { 87 // Return a copy of the key, rather than a reference, 88 // so that the key data cannot be modified from outside 89 return this.key.clone(); 90 } 91 92 public String getAlgorithm() { 93 return "DES"; 94 } 95 96 public String getFormat() { 97 return "RAW"; 98 } 99 100 /** 101 * Calculates a hash code value for the object. 102 * Objects that are equal will also have the same hashcode. 103 */ 104 public int hashCode() { 105 int retval = 0; 106 for (int i = 1; i < this.key.length; i++) { 107 retval += this.key[i] * i; 108 } 109 return(retval ^= "des".hashCode()); 110 } 111 112 public boolean equals(Object obj) { 113 if (this == obj) 114 return true; 115 116 if (!(obj instanceof SecretKey)) 117 return false; 118 119 String thatAlg = ((SecretKey)obj).getAlgorithm(); 120 if (!(thatAlg.equalsIgnoreCase("DES"))) 121 return false; 122 123 byte[] thatKey = ((SecretKey)obj).getEncoded(); 124 boolean ret = MessageDigest.isEqual(this.key, thatKey); 125 java.util.Arrays.fill(thatKey, (byte)0x00); 126 return ret; 127 } 128 129 /** 130 * readObject is called to restore the state of this key from 131 * a stream. 132 */ 133 private void readObject(java.io.ObjectInputStream s) 134 throws java.io.IOException, ClassNotFoundException 135 { 136 s.defaultReadObject(); 137 key = key.clone(); 138 } 139 140 /** 141 * Replace the DES key to be serialized. 142 * 143 * @return the standard KeyRep object to be serialized 144 * 145 * @throws java.io.ObjectStreamException if a new object representing 146 * this DES key could not be created 147 */ 148 private Object writeReplace() throws java.io.ObjectStreamException { 149 return new KeyRep(KeyRep.Type.SECRET, 150 getAlgorithm(), 151 getFormat(), 152 getEncoded()); 153 } 154} 155