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 26 package com.sun.crypto.provider; 27 28 import java.lang.ref.Reference; 29 import java.security.MessageDigest; 30 import java.security.KeyRep; 31 import java.security.InvalidKeyException; 32 import javax.crypto.SecretKey; 33 import javax.crypto.spec.DESedeKeySpec; 34 35 import jdk.internal.ref.CleanerFactory; 36 37 /** 38 * This class represents a DES-EDE key. 39 * 40 * @author Jan Luehe 41 * 42 */ 43 44 final class DESedeKey implements SecretKey { 45 46 static final long serialVersionUID = 2463986565756745178L; 47 48 private byte[] key; 49 50 /** 51 * Creates a DES-EDE key from a given key. 52 * 53 * @param key the given key 54 * 55 * @exception InvalidKeyException if the given key has a wrong size 56 */ DESedeKey(byte[] key)57 DESedeKey(byte[] key) throws InvalidKeyException { 58 this(key, 0); 59 } 60 61 /** 62 * Uses the first 24 bytes in <code>key</code>, beginning at 63 * <code>offset</code>, as the DES-EDE key 64 * 65 * @param key the buffer with the DES-EDE key 66 * @param offset the offset in <code>key</code>, where the DES-EDE key 67 * starts 68 * 69 * @exception InvalidKeyException if the given key has a wrong size 70 */ DESedeKey(byte[] key, int offset)71 DESedeKey(byte[] key, int offset) throws InvalidKeyException { 72 73 if (key==null || ((key.length-offset)<DESedeKeySpec.DES_EDE_KEY_LEN)) { 74 throw new InvalidKeyException("Wrong key size"); 75 } 76 this.key = new byte[DESedeKeySpec.DES_EDE_KEY_LEN]; 77 System.arraycopy(key, offset, this.key, 0, 78 DESedeKeySpec.DES_EDE_KEY_LEN); 79 DESKeyGenerator.setParityBit(this.key, 0); 80 DESKeyGenerator.setParityBit(this.key, 8); 81 DESKeyGenerator.setParityBit(this.key, 16); 82 83 // Use the cleaner to zero the key when no longer referenced 84 final byte[] k = this.key; 85 CleanerFactory.cleaner().register(this, 86 () -> java.util.Arrays.fill(k, (byte)0x00)); 87 } 88 getEncoded()89 public byte[] getEncoded() { 90 // The key is zeroized by finalize() 91 // The reachability fence ensures finalize() isn't called early 92 byte[] result = key.clone(); 93 Reference.reachabilityFence(this); 94 return result; 95 } 96 getAlgorithm()97 public String getAlgorithm() { 98 return "DESede"; 99 } 100 getFormat()101 public String getFormat() { 102 return "RAW"; 103 } 104 105 /** 106 * Calculates a hash code value for the object. 107 * Objects that are equal will also have the same hashcode. 108 */ hashCode()109 public int hashCode() { 110 int retval = 0; 111 for (int i = 1; i < this.key.length; i++) { 112 retval += this.key[i] * i; 113 } 114 return(retval ^= "desede".hashCode()); 115 } 116 equals(Object obj)117 public boolean equals(Object obj) { 118 if (this == obj) 119 return true; 120 121 if (!(obj instanceof SecretKey)) 122 return false; 123 124 String thatAlg = ((SecretKey)obj).getAlgorithm(); 125 if (!(thatAlg.equalsIgnoreCase("DESede")) 126 && !(thatAlg.equalsIgnoreCase("TripleDES"))) 127 return false; 128 129 byte[] thatKey = ((SecretKey)obj).getEncoded(); 130 boolean ret = MessageDigest.isEqual(this.key, thatKey); 131 java.util.Arrays.fill(thatKey, (byte)0x00); 132 return ret; 133 } 134 135 /** 136 * readObject is called to restore the state of this key from 137 * a stream. 138 */ readObject(java.io.ObjectInputStream s)139 private void readObject(java.io.ObjectInputStream s) 140 throws java.io.IOException, ClassNotFoundException 141 { 142 s.defaultReadObject(); 143 key = key.clone(); 144 } 145 146 /** 147 * Replace the DESede key to be serialized. 148 * 149 * @return the standard KeyRep object to be serialized 150 * 151 * @throws java.io.ObjectStreamException if a new object representing 152 * this DESede key could not be created 153 */ writeReplace()154 private Object writeReplace() throws java.io.ObjectStreamException { 155 return new KeyRep(KeyRep.Type.SECRET, 156 getAlgorithm(), 157 getFormat(), 158 getEncoded()); 159 } 160 } 161