001: /*
002:
003: * Copyright (C) 1995-2000 The Cryptix Foundation Limited.
004: * All rights reserved.
005: *
006: * Use, modification, copying and distribution of this software is subject
007: * the terms and conditions of the Cryptix General Licence. You should have
008: * received a copy of the Cryptix General Licence along with this library;
009: * if not, you can download a copy from http://www.cryptix.org/ .
010:
011:
012: * This class implement DES Algorithm. Just modified the source code to suite
013: * our requirements
014: *
015: * @ created 13-12-2001
016: * @ Author Rajesh T
017: * @ source cryptix
018:
019: * The DES cipher (in ECB mode).
020: *
021: * Parts of this code Copyright (C) 1996 Geoffrey Keating. All rights reserved.
022: *
023: * Its use is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
024: * as long as the following conditions are adhered to.
025: *
026: * Copyright remains Geoffrey Keating's, and as such any Copyright notices in
027: * the code are not to be removed. If this code is used in a product,
028: * Geoffrey Keating should be given attribution as the author of the parts used.
029: * This can be in the form of a textual message at program startup or
030: * in documentation (online or textual) provided with the package.
031: *
032: * Redistribution and use in source and binary forms, with or without
033: * modification, are permitted provided that the following conditions
034: * are met:
035: * 1. Redistributions of source code must retain the copyright
036: * notice, this list of conditions and the following disclaimer.
037: * 2. Redistributions in binary form must reproduce the above copyright
038: * notice, this list of conditions and the following disclaimer in the
039: * documentation and/or other materials provided with the distribution.
040: * 3. All advertising materials mentioning features or use of this software
041: * must display the following acknowledgement:
042: * This product includes software developed by Geoffrey Keating
043: * (geoffk@discus.anu.edu.au)
044: *
045: * THIS SOFTWARE IS PROVIDED BY GEOFFREY KEATING ``AS IS'' AND
046: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
047: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
048: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
049: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
050: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
051: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
052: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
053: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
054: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
055: * SUCH DAMAGE.
056: *
057: */
058: /* Parts of this code (in particular, the string representing SP_TRANS)
059: * are Copyright (C) 1995 Eric Young (eay@mincom.oz.au). All rights reserved.
060: *
061: * Its use is FREE FOR COMMERCIAL AND NON-COMMERCIAL USE
062: * as long as the following conditions are adhered to.
063: *
064: * Copyright remains Eric Young's, and as such any Copyright notices in
065: * the code are not to be removed. If this code is used in a product,
066: * Eric Young should be given attribution as the author of the parts used.
067: * This can be in the form of a textual message at program startup or
068: * in documentation (online or textual) provided with the package.
069: *
070: * Redistribution and use in source and binary forms, with or without
071: * modification, are permitted provided that the following conditions
072: * are met:
073: * 1. Redistributions of source code must retain the copyright
074: * notice, this list of conditions and the following disclaimer.
075: * 2. Redistributions in binary form must reproduce the above copyright
076: * notice, this list of conditions and the following disclaimer in the
077: * documentation and/or other materials provided with the distribution.
078: * 3. All advertising materials mentioning features or use of this software
079: * must display the following acknowledgement:
080: * This product includes software developed by Eric Young (eay@mincom.oz.au)
081: *
082: * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
083: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
084: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
085: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
086: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
087: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
088: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
089: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
090: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
091: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
092: * SUCH DAMAGE.
093: */
094:
095: package com.sun.portal.kssl;
096:
097: import com.sun.portal.ksecurity.Key;
098: import com.sun.portal.ksecurity.SecretKey;
099: import com.sun.portal.ksecurity.KeyBuilder;
100: import com.sun.portal.ksecurity.CryptoException;
101:
102: public final class DES extends BlockCipher {
103:
104: private byte type;
105: /** Local certificate key. */
106: private Key ckey = null;
107:
108: private static final int ROUNDS = 16, // number of encryption/decryption rounds
109: KEY_LENGTH = 8, // DES key length in bytes
110: INTERNAL_KEY_LENGTH = 2 * ROUNDS; // number of elements in key schedule
111:
112: /* Table for PC2 permutations in key schedule computation. */
113: private static final int[] SKB = new int[8 * 64];
114:
115: /* Table for S-boxes and permutations, used in encrypt_base. */
116: private static final int SP_TRANS[] = new int[8 * 64];
117:
118: /* Build the SKB and SP_TRANS tables */
119: static {
120: // build the SKB table
121: // represent the bit number that each permutated bit is derived from
122: // according to FIPS-46
123: String cd = "D]PKESYM`UBJ\\@RXA`I[T`HC`LZQ"
124: + "\\PB]TL`[C`JQ@Y`HSXDUIZRAM`EK";
125: int j, s, bit;
126: int count = 0;
127: int offset = 0;
128: for (int i = 0; i < cd.length(); i++) {
129: s = cd.charAt(i) - '@';
130: if (s != 32) {
131: bit = 1 << count++;
132: for (j = 0; j < 64; j++)
133: if ((bit & j) != 0)
134: SKB[offset + j] |= 1 << s;
135: if (count == 6) {
136: offset += 64;
137: count = 0;
138: }
139: }
140: }
141:
142: // build the SP_TRANS table
143: // I'd _really_ like to just say 'SP_TRANS = { ... }', but
144: // that would be terribly inefficient (code size + time).
145: // Instead we use a compressed representation --GK
146: String spt = "g3H821:80:H03BA0@N1290BAA88::3112aIH8:8282@0@AH0:1W3A8P810@22;22"
147: + "A18^@9H9@129:<8@822`?:@0@8PH2H81A19:G1@03403A0B1;:0@1g192:@919AA"
148: + "0A109:W21492H@0051919811:215011139883942N8::3112A2:31981jM118::A"
149: + "101@I88:1aN0<@030128:X;811`920:;H0310D1033@W980:8A4@804A3803o1A2"
150: + "021B2:@1AH023GA:8:@81@@12092B:098042P@:0:A0HA9>1;289:@1804:40Ph="
151: + "1:H0I0HP0408024bC9P8@I808A;@0@0PnH0::8:19J@818:@iF0398:8A9H0<13@"
152: + "001@11<8;@82B01P0a2989B:0AY0912889bD0A1@B1A0A0AB033O91182440A9P8"
153: + "@I80n@1I03@1J828212A`A8:12B1@19A9@9@8^B:0@H00<82AB030bB840821Q:8"
154: + "310A302102::A1::20A1;8"; // OK, try to type _that_!
155: // [526 chars, 3156 bits]
156: // The theory is that each bit position in each int of SP_TRANS is
157: // set in exactly 32 entries. We keep track of set bits.
158: offset = 0;
159: int k, c, param;
160: for (int i = 0; i < 32; i++) // each bit position
161: {
162: k = -1; // pretend the -1th bit was set
163: bit = 1 << i;
164: for (j = 0; j < 32; j++) // each set bit
165: {
166: // Each character consists of two three-bit values:
167: c = spt.charAt(offset >> 1) - '0' >> (offset & 1) * 3 & 7;
168: offset++;
169: if (c < 5) {
170: // values 0...4 indicate a set bit 1...5 positions
171: // from the previous set bit
172: k += c + 1;
173: SP_TRANS[k] |= bit;
174: continue;
175: }
176: // other values take at least an additional parameter:
177: // the next value in the sequence.
178: param = spt.charAt(offset >> 1) - '0' >> (offset & 1) * 3 & 7;
179: offset++;
180: if (c == 5) {
181: // indicates a bit set param+6 positions from
182: // the previous set bit
183: k += param + 6;
184: SP_TRANS[k] |= bit;
185: } else if (c == 6) {
186: // indicates a bit set (param * 64) + 1 positions
187: // from the previous set bit
188: k += (param << 6) + 1;
189: SP_TRANS[k] |= bit;
190: } else {
191: // indicates that we should skip (param * 64) positions,
192: // then process the next value which will be in the range
193: // 0...4.
194: k += param << 6;
195: j--;
196: }
197: }
198: }
199: }
200:
201: /* The internal key schedule */
202: private int[] sKey = new int[INTERNAL_KEY_LENGTH];
203:
204: public DES() {
205: type = Cipher.ALG_DES;
206: BLOCK_SIZE = 8;
207: }
208:
209: public byte getAlgorithm() {
210: return Cipher.ALG_DES;
211: }
212:
213: public void init(Key theKey, byte theMode) throws CryptoException {
214: if ((theKey.getType() != KeyBuilder.TYPE_DES)
215: || ((theMode != Cipher.MODE_ENCRYPT) && (theMode != Cipher.MODE_DECRYPT))) {
216: throw new CryptoException(CryptoException.ILLEGAL_VALUE);
217: }
218: mode = theMode;
219: ckey = theKey;
220:
221: byte[] userkey = new byte[(theKey.getSize() + 7) >>> 3];
222: ((SecretKey) theKey).getKey(userkey, (short) 0);
223:
224: if (userkey == null) {
225: throw new CryptoException(CryptoException.ILLEGAL_VALUE);
226: }
227: //throw new CryptoException("Null user key");
228:
229: if (userkey.length != KEY_LENGTH) {
230: throw new CryptoException(CryptoException.ILLEGAL_VALUE);
231: }
232: //throw new CryptoException("Invalid user key length");
233:
234: int i = 0;
235: int c = (userkey[i++] & 0xFF) | (userkey[i++] & 0xFF) << 8
236: | (userkey[i++] & 0xFF) << 16 | (userkey[i++]) << 24;
237: int d = (userkey[i++] & 0xFF) | (userkey[i++] & 0xFF) << 8
238: | (userkey[i++] & 0xFF) << 16 | (userkey[i]) << 24;
239:
240: int t = ((d >>> 4) ^ c) & 0x0F0F0F0F;
241: c ^= t;
242: d ^= t << 4;
243: t = ((c << 18) ^ c) & 0xCCCC0000;
244: c ^= t ^ t >>> 18;
245: t = ((d << 18) ^ d) & 0xCCCC0000;
246: d ^= t ^ t >>> 18;
247: t = ((d >>> 1) ^ c) & 0x55555555;
248: c ^= t;
249: d ^= t << 1;
250: t = ((c >>> 8) ^ d) & 0x00FF00FF;
251: d ^= t;
252: c ^= t << 8;
253: t = ((d >>> 1) ^ c) & 0x55555555;
254: c ^= t;
255: d ^= t << 1;
256:
257: d = (d & 0x000000FF) << 16 | (d & 0x0000FF00)
258: | (d & 0x00FF0000) >>> 16 | (c & 0xF0000000) >>> 4;
259: c &= 0x0FFFFFFF;
260:
261: int s;
262: int j = 0;
263:
264: for (i = 0; i < ROUNDS; i++) {
265: if ((0x7EFC >> i & 1) == 1) {
266: c = (c >>> 2 | c << 26) & 0x0FFFFFFF;
267: d = (d >>> 2 | d << 26) & 0x0FFFFFFF;
268: } else {
269: c = (c >>> 1 | c << 27) & 0x0FFFFFFF;
270: d = (d >>> 1 | d << 27) & 0x0FFFFFFF;
271: }
272: s = SKB[c & 0x3F]
273: | SKB[0x040 | (((c >>> 6) & 0x03) | ((c >>> 7) & 0x3C))]
274: | SKB[0x080 | (((c >>> 13) & 0x0F) | ((c >>> 14) & 0x30))]
275: | SKB[0x0C0 | (((c >>> 20) & 0x01)
276: | ((c >>> 21) & 0x06) | ((c >>> 22) & 0x38))];
277: t = SKB[0x100 | (d & 0x3F)]
278: | SKB[0x140 | (((d >>> 7) & 0x03) | ((d >>> 8) & 0x3c))]
279: | SKB[0x180 | ((d >>> 15) & 0x3F)]
280: | SKB[0x1C0 | (((d >>> 21) & 0x0F) | ((d >>> 22) & 0x30))];
281:
282: sKey[j++] = t << 16 | (s & 0x0000FFFF);
283: s = s >>> 16 | (t & 0xFFFF0000);
284: sKey[j++] = s << 4 | s >>> 28;
285: }
286:
287: // Reverse the subkeys if we're decrypting
288: // Best illustrated by example: 1 2 3 4 5 6 7 8 -> 7 8 5 6 3 4 1 2
289: if (mode == Cipher.MODE_DECRYPT) {
290: for (i = 0; i < 16; i++) {
291: j = 30 - i + (i % 2 * 2);
292: t = sKey[i];
293: sKey[i] = sKey[j];
294: sKey[j] = t;
295: }
296: }
297:
298: }
299:
300: protected void coreCrypt(byte[] in, int inOffset, byte[] out,
301: int outOffset) {
302: int L = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
303: | (in[inOffset++] & 0xFF) << 16
304: | (in[inOffset++]) << 24;
305: int R = (in[inOffset++] & 0xFF) | (in[inOffset++] & 0xFF) << 8
306: | (in[inOffset++] & 0xFF) << 16 | (in[inOffset]) << 24;
307:
308: // Initial permutation
309: int t = ((R >>> 4) ^ L) & 0x0F0F0F0F;
310: L ^= t;
311: R ^= t << 4;
312: t = ((L >>> 16) ^ R) & 0x0000FFFF;
313: R ^= t;
314: L ^= t << 16;
315: t = ((R >>> 2) ^ L) & 0x33333333;
316: L ^= t;
317: R ^= t << 2;
318: t = ((L >>> 8) ^ R) & 0x00FF00FF;
319: R ^= t;
320: L ^= t << 8;
321: t = ((R >>> 1) ^ L) & 0x55555555;
322: L ^= t;
323: R ^= t << 1;
324:
325: // look! we fit all four variables (plus the class itself)
326: // into short byte-codes!
327: int u = R << 1 | R >>> 31;
328: R = L << 1 | L >>> 31;
329: L = u;
330:
331: for (int i = 0; i < INTERNAL_KEY_LENGTH;) {
332: u = R ^ sKey[i++];
333: t = R ^ sKey[i++];
334: t = t >>> 4 | t << 28;
335: L ^= (SP_TRANS[0x040 | (t & 0x3F)]
336: | SP_TRANS[0x0C0 | ((t >>> 8) & 0x3F)]
337: | SP_TRANS[0x140 | ((t >>> 16) & 0x3F)]
338: | SP_TRANS[0x1C0 | ((t >>> 24) & 0x3F)]
339: | SP_TRANS[u & 0x3F]
340: | SP_TRANS[0x080 | ((u >>> 8) & 0x3F)]
341: | SP_TRANS[0x100 | ((u >>> 16) & 0x3F)] | SP_TRANS[0x180 | ((u >>> 24) & 0x3F)]);
342:
343: u = L ^ sKey[i++];
344: t = L ^ sKey[i++];
345: t = t >>> 4 | t << 28;
346: R ^= (SP_TRANS[0x040 | (t & 0x3F)]
347: | SP_TRANS[0x0C0 | ((t >>> 8) & 0x3F)]
348: | SP_TRANS[0x140 | ((t >>> 16) & 0x3F)]
349: | SP_TRANS[0x1C0 | ((t >>> 24) & 0x3F)]
350: | SP_TRANS[u & 0x3F]
351: | SP_TRANS[0x080 | ((u >>> 8) & 0x3F)]
352: | SP_TRANS[0x100 | ((u >>> 16) & 0x3F)] | SP_TRANS[0x180 | ((u >>> 24) & 0x3F)]);
353: }
354: R = R >>> 1 | R << 31;
355: L = L >>> 1 | L << 31;
356:
357: // Final permutation
358: t = (R >>> 1 ^ L) & 0x55555555;
359: L ^= t;
360: R ^= t << 1;
361: t = (L >>> 8 ^ R) & 0x00FF00FF;
362: R ^= t;
363: L ^= t << 8;
364: t = (R >>> 2 ^ L) & 0x33333333;
365: L ^= t;
366: R ^= t << 2;
367: t = (L >>> 16 ^ R) & 0x0000FFFF;
368: R ^= t;
369: L ^= t << 16;
370: t = (R >>> 4 ^ L) & 0x0F0F0F0F;
371:
372: L ^= t;
373: R ^= (t << 4);
374:
375: out[outOffset++] = (byte) (L);
376: out[outOffset++] = (byte) (L >> 8);
377: out[outOffset++] = (byte) (L >> 16);
378: out[outOffset++] = (byte) (L >> 24);
379: out[outOffset++] = (byte) (R);
380: out[outOffset++] = (byte) (R >> 8);
381: out[outOffset++] = (byte) (R >> 16);
382: out[outOffset] = (byte) (R >> 24);
383: }
384: }
|