1/* 2 * Copyright (c) 1997, 2007, 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.InvalidKeyException; 29 30/** 31 * This class implements the Triple DES algorithm (DES encryption, followed by 32 * DES decryption, followed by DES encryption) on a byte array of size 33 * <code>DES_BLOCK_SIZE</code>. Each DES operation has its own key. 34 * 35 * @author Gigi Ankeny 36 * @author Jan Luehe 37 * 38 * 39 * @see DESConstants 40 * @see DESCipher 41 */ 42 43final class DESedeCrypt extends DESCrypt implements DESConstants { 44 45 /* 46 * the expanded key used in encrypt/decrypt/encrypt phase 47 */ 48 private byte[] key1 = null; 49 private byte[] key2 = null; 50 private byte[] key3 = null; 51 private byte[] buf1, buf2; 52 53 /* 54 * constructor 55 */ 56 DESedeCrypt() { 57 buf1 = new byte[DES_BLOCK_SIZE]; 58 buf2 = new byte[DES_BLOCK_SIZE]; 59 } 60 61 void init(boolean decrypting, String algorithm, byte[] keys) 62 throws InvalidKeyException { 63 if (!algorithm.equalsIgnoreCase("DESede") 64 && !algorithm.equalsIgnoreCase("TripleDES")) { 65 throw new InvalidKeyException 66 ("Wrong algorithm: DESede or TripleDES required"); 67 } 68 if (keys.length != DES_BLOCK_SIZE * 3) { 69 throw new InvalidKeyException("Wrong key size"); 70 } 71 72 byte[] keybuf = new byte[DES_BLOCK_SIZE]; 73 74 // retrieve the first key 75 key1 = new byte[128]; 76 System.arraycopy(keys, 0, keybuf, 0, DES_BLOCK_SIZE); 77 expandKey(keybuf); 78 System.arraycopy(expandedKey, 0, key1, 0, 128); 79 80 // check if the third key is the same 81 if (keyEquals(keybuf, 0, keys, DES_BLOCK_SIZE*2, DES_BLOCK_SIZE)) { 82 key3 = key1; 83 } else { 84 key3 = new byte[128]; 85 System.arraycopy(keys, DES_BLOCK_SIZE*2, keybuf, 0, 86 DES_BLOCK_SIZE); 87 expandKey(keybuf); 88 System.arraycopy(expandedKey, 0, key3, 0, 128); 89 } 90 91 // retrieve the second key 92 key2 = new byte[128]; 93 System.arraycopy(keys, DES_BLOCK_SIZE, keybuf, 0, DES_BLOCK_SIZE); 94 expandKey(keybuf); 95 System.arraycopy(expandedKey, 0, key2, 0, 128); 96 97 } 98 99 /** 100 * Performs encryption operation. 101 * 102 * <p>The input plain text <code>plain</code>, starting at 103 * <code>plainOffset</code> and ending at 104 * <code>(plainOffset + blockSize - 1)</code>, is encrypted. 105 * The result is stored in <code>cipher</code>, starting at 106 * <code>cipherOffset</code>. 107 * 108 * @param plain the buffer with the input data to be encrypted 109 * @param plainOffset the offset in <code>plain</code> 110 * @param cipher the buffer for the result 111 * @param cipherOffset the offset in <code>cipher</code> 112 */ 113 void encryptBlock(byte[] plain, int plainOffset, 114 byte[] cipher, int cipherOffset) 115 { 116 expandedKey = key1; 117 decrypting = false; 118 cipherBlock(plain, plainOffset, buf1, 0); 119 120 expandedKey = key2; 121 decrypting = true; 122 cipherBlock(buf1, 0, buf2, 0); 123 124 expandedKey = key3; 125 decrypting = false; 126 cipherBlock(buf2, 0, cipher, cipherOffset); 127 } 128 129 /** 130 * Performs decryption operation. 131 * 132 * <p>The input cipher text <code>cipher</code>, starting at 133 * <code>cipherOffset</code> and ending at 134 * <code>(cipherOffset + blockSize - 1)</code>, is decrypted. 135 * The result is stored in <code>plain</code>, starting at 136 * <code>plainOffset</code>. 137 * 138 * @param cipher the buffer with the input data to be decrypted 139 * @param cipherOffset the offset in <code>cipherOffset</code> 140 * @param plain the buffer for the result 141 * @param plainOffset the offset in <code>plain</code> 142 */ 143 void decryptBlock(byte[] cipher, int cipherOffset, 144 byte[] plain, int plainOffset) 145 { 146 expandedKey = key3; 147 decrypting = true; 148 cipherBlock(cipher, cipherOffset, buf1, 0); 149 150 expandedKey = key2; 151 decrypting = false; 152 cipherBlock(buf1, 0, buf2, 0); 153 154 expandedKey = key1; 155 decrypting = true; 156 cipherBlock(buf2, 0, plain, plainOffset); 157 } 158 159 private boolean keyEquals(byte[] key1, int off1, 160 byte[] key2, int off2, int len) { 161 162 for (int i=0; i<len; i++) { 163 if (key1[i+off1] != key2[i+off2]) 164 return false; 165 } 166 return true; 167 } 168} 169