View Javadoc
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  
26  package com.sun.crypto.provider;
27  
28  import 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  
43  final 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 }