001: /*
002: *
003: *
004: * Copyright 1990-2007 Sun Microsystems, Inc. All Rights Reserved.
005: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER
006: *
007: * This program is free software; you can redistribute it and/or
008: * modify it under the terms of the GNU General Public License version
009: * 2 only, as published by the Free Software Foundation.
010: *
011: * This program is distributed in the hope that it will be useful, but
012: * WITHOUT ANY WARRANTY; without even the implied warranty of
013: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014: * General Public License version 2 for more details (a copy is
015: * included at /legal/license.txt).
016: *
017: * You should have received a copy of the GNU General Public License
018: * version 2 along with this work; if not, write to the Free Software
019: * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA
021: *
022: * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
023: * Clara, CA 95054 or visit www.sun.com if you need additional
024: * information or have any questions.
025: */
026:
027: package com.sun.midp.crypto;
028:
029: /**
030: * DES cipher implementation.
031: */
032: class DES_ECB extends BlockCipherBase {
033: /** True, if this class is being used for triple DES (EDE). */
034: private boolean tripleDes;
035:
036: /** Algorithm of the key. */
037: protected String keyAlgorithm;
038:
039: /** DES ciphers encrypt/decrypt in block size of 8 bytes. */
040: protected static final int BLOCK_SIZE = 8;
041:
042: /** s0p. */
043: private static final int s0p[] = initTable(0x40410100,
044: 0x72cf4bacb769d40aL, 0x2853f695813e1de0L,
045: 0xf5a7295e13cb8c6L, 0xf36d49a024d78e1bL);
046:
047: /** s1p. */
048: private static final int s1p[] = initTable(0x08021002,
049: 0xf06c93a62d1a5ec1L, 0x4bd27805b7e9843fL,
050: 0x5ea7f590834d287bL, 0xe2091f6cd43ab1c6L);
051:
052: /** s2p. */
053: private static final int s2p[] = initTable(0x20808020,
054: 0xc71da4d35268f98eL, 0xa719f2ce5b6304bL,
055: 0x71829a6d073ea4f8L, 0xbc4f25d350e9cb16L);
056:
057: /** s3p. */
058: private static final int s3p[] = initTable(0x02080201,
059: 0x7a1f0cb5e9839748L, 0xd6216bc2305eadf4L,
060: 0xd3496a1cb0250de2L, 0x8f74f1a756cb389eL);
061:
062: /** s4p. */
063: private static final int s4p[] = initTable(0x01002084,
064: 0x842fda7c4196bde0L, 0x6853a7091bf5c23eL,
065: 0xeb5c419a86f07825L, 0xb20fde346da317c9L);
066:
067: /** s5p. */
068: private static final int s5p[] = initTable(0x10040408,
069: 0x950e52b43f68a9c7L, 0x4bd021edfc83167aL,
070: 0x38a7e50a82d45f61L, 0xf64b9c7029bec31dL);
071:
072: /** s6p. */
073: private static final int s6p[] = initTable(0x80200840,
074: 0x215cfa304d968769L, 0xd2af05c3eb78be14L,
075: 0xb6e9214edb301c85L, 0xd5392f478afc76aL);
076:
077: /** s7p. */
078: private static final int s7p[] = initTable(0x04104010,
079: 0xde30a5cf18637b9cL, 0x275af90684bd42e1L,
080: 0x429f3806dba5e15aL, 0xf4c963bc1e708d27L);
081:
082: /** initPermRight. */
083: private static int[] initPermRight = initPerm(128, 32, 2, -3,
084: 0xc3b3432020332020L, 0x83b3432020332020L);
085: /** initPermLeft. */
086: private static int[] initPermLeft = initPerm(128, 32, 2, -3,
087: 0x8742032067420320L, 0x4742032067420320L);
088: /** perm. */
089: private static int[] perm = initPerm(64, 64, 4, -1,
090: 0x4420411201004021L, 0x1001200101000000L);
091:
092: /**
093: * Data used for key expansion.
094: */
095: private static byte[] expandData = ("\020\0313KM1L3}\014I1JT*}\025"
096: + "\017\0128R=M;KM,Zx<I1X\017\020}\013}\000(R=}\021-H<Zk\020"
097: + "%}\001Z5P8I(R3}\014:\134;\017*R5P8I1{}\014:\134-U1\017y1}"
098: + "\023<M0T-U:I4KH\015tM0KqZ94KxR3[\017\013=H<Zx<S}\000(R=MI"
099: + "\020\000\134*}\031-H<IL3}\033}\0002\017LI1JT*}\025;KM1L3P"
100: + "\016u:I4KxI}\023<M0K5\016:94KxR3[<M0KqJ\0169(R3}\014:\134"
101: + ";qZ5P8\0174<:\134-U:I=P8I1}\023\020\005SM1L3}\03391JT*}"
102: + "\0313\017\034:=M;KM1Rx<I1J8\016\014S}\000(R=MI-H<Zx\01751Z"
103: + "5P8I1J3}\014:\134-\0171=P8I1}\023t:\134-U:R\020\040I}\023<"
104: + "M0K5U:I4K}\021\016,U0KqZ5<KxR3}\024\017\0238<Zx<I}\010(R=M"
105: + ";=\020\0222}\031-H<Z<3}\033}\000(\134\020\03391JT*}\0313KM"
106: + "1L3}\014\017!JI4KxR}\013<M0K}\005\016-<KxR3}\024M0KqZ9\020"
107: + ")J3}\014:\134-}\001Z5P8I(\020=*\134-U:I4X8I1}\023<<\017"
108: + "\010U1L3}\033iJT*}\031-S\020\002MM;KM1L}\000<I1JT:\017\021"
109: + "}\010(R=M;=H<Zx<S\020\032<3}\033}\000(\134*}\031-H<I\020$X"
110: + "8I1}\023<<:\134-U:I=\0172}\013<M0K}\005:I4KxI\016\042HKqZ5"
111: + "P3xR3}\014U\017\035,Zx<I1X(R=M;K8\017\015}\021-H<Zk}\033}"
112: + "\000(R2\017AJT*}\031-SM1L3}\0339\020\024}\000<I1JT:=M;KM1"
113: + "R\01683xR3}\014U0KqZ5<\017c}\014:\134-U1Z5P8I1J\020(T-U:I"
114: + "4KHI1}\023<M*\020\004IL3}\033}\0002T*}\031-HU\017U;KM1L3P"
115: + "<I1JT*M\016\001X(R=M;K8<Zx<I\017C}\033}\000(R2}\031-H<Z<"
116: + "\020+HI1}\023<M*\134-U:I4X\015#[<M0KqJI4KxR\016<;qZ5P8pR3"
117: + "}\014:H\017\011Rx<I1J8R=M;KM,\016\025I-H<Zx}\013}\000(R="
118: + "\017\0302T*}\031-HU1L3}\033i\017\003P<I1JT*MM;KM1L\0160pR"
119: + "3}\014:HKqZ5P3\016;t:\134-U:R5P8I1{\02035U:I4K}\0211}\023"
120: + "<M0T").getBytes();
121:
122: /** DES key data. */
123: private byte[][] dkey;
124:
125: /**
126: * Constructor.
127: *
128: * @param useTripleDes true if the class is being used for triple DES
129: *
130: */
131: public DES_ECB(boolean useTripleDes) {
132: super (BLOCK_SIZE);
133: tripleDes = useTripleDes;
134:
135: if (useTripleDes) {
136: keyAlgorithm = "DESEDE";
137: } else {
138: keyAlgorithm = "DES";
139: }
140: }
141:
142: /**
143: * Called by the factory method to set the mode and padding parameters.
144: * Need because Class.newInstance does not take args.
145: *
146: * @param mode the mode parsed from the transformation parameter of
147: * getInstance and upper cased
148: * @param padding the paddinge parsed from the transformation parameter of
149: * getInstance and upper cased
150: */
151: protected void setChainingModeAndPadding(String mode, String padding)
152: throws NoSuchPaddingException {
153: // Note: The chaining mode is implicitly set by using this class.
154:
155: setPadding(padding);
156: }
157:
158: /**
159: * Initializes this cipher with a key and a set of algorithm
160: * parameters.
161: *
162: * @param mode the operation mode of this cipher
163: * @param key the encryption key
164: * @param params the algorithm parameters
165: *
166: * @exception java.security.InvalidKeyException if the given key
167: * is inappropriate for initializing this cipher
168: * @exception java.security.InvalidAlgorithmParameterException
169: * if the given algorithm parameters are inappropriate for this cipher
170: */
171: public void init(int mode, Key key, CryptoParameter params)
172: throws InvalidKeyException,
173: InvalidAlgorithmParameterException {
174: doInit(mode, keyAlgorithm, key, false, null);
175: }
176:
177: /**
178: * Initializes key.
179: * @param data key data
180: * @param mode cipher mode
181: * @exception InvalidKeyException if the given key is inappropriate
182: * for this cipher
183: */
184: protected void initKey(byte[] data, int mode)
185: throws InvalidKeyException {
186:
187: if (data.length != (tripleDes ? 24 : 8)) {
188: throw new InvalidKeyException();
189: }
190:
191: int keyCount = data.length >> 3;
192: dkey = new byte[keyCount][];
193: for (int i = 0; i < keyCount; i++) {
194: dkey[i] = expandKey(data, i << 3);
195: }
196: }
197:
198: /**
199: * Depending on the mode, either encrypts
200: * or decrypts the data in the queue.
201: * @param out will contain the result of encryption
202: * or decryption operation
203: * @param offset is the offset in out
204: */
205: protected void processBlock(byte[] out, int offset) {
206:
207: if (dkey.length == 1) {
208: cipherBlock(0, mode == Cipher.ENCRYPT_MODE);
209: } else {
210: if (mode == Cipher.ENCRYPT_MODE) {
211: cipherBlock(0, true);
212: cipherBlock(1, false);
213: cipherBlock(2, true);
214: } else {
215: cipherBlock(2, false);
216: cipherBlock(1, true);
217: cipherBlock(0, false);
218: }
219: }
220: System.arraycopy(holdData, 0, out, offset, BLOCK_SIZE);
221: holdCount = 0;
222: }
223:
224: /**
225: * Initializes data for permutation.
226: * @param value seed value
227: * @param period perion for value modification
228: * @param divisor divisor of value
229: * @param offset initial offset in the table
230: * @param deltas1 packed offsets for elements 0 - 15
231: * @param deltas2 packed offsets for elements 16 - 31
232: * @return initialized data
233: */
234: private static int[] initPerm(int value, int period, int divisor,
235: int offset, long deltas1, long deltas2) {
236:
237: int[] result = new int[256];
238: int count = 0;
239:
240: while (true) {
241:
242: offset += ((((count & 0x1f) < 16 ? deltas1 : deltas2) >> ((15 - count & 0xf) << 2)) & 0xf) + 1;
243:
244: if (offset > 1023) {
245: return result;
246: }
247:
248: count++;
249:
250: if (count > 1 && count % period == 1) {
251: value = value == 1 ? 128 : (value / divisor);
252: }
253:
254: result[offset >> 2] |= (value << ((3 - offset & 3) << 3));
255: }
256: }
257:
258: /**
259: * Initializes static data used by DES.
260: * @param bitmask mask of bits used in this table
261: * @param l1 order of words 0 - 15
262: * @param l2 order of words 16 - 31
263: * @param l3 order of words 32 - 47
264: * @param l4 order of words 48 - 63
265: * @return the table
266: */
267: private static final int[] initTable(int bitmask, long l1, long l2,
268: long l3, long l4) {
269:
270: int[] words = new int[16];
271: int count = 1;
272:
273: for (int i = 0; i < 8; i++) {
274:
275: int mask;
276: if ((mask = bitmask & (0xf << (i << 2))) == 0) {
277: continue;
278: }
279:
280: for (int j = 0; j < count; j++) {
281: words[count + j] = words[j] | mask;
282: }
283: count += count;
284: }
285:
286: int[] data = new int[64];
287: for (int i = 0; i < 64; i++) {
288: data[i] = words[((int) ((i < 32 ? (i < 16 ? l1 : l2)
289: : (i < 48 ? l3 : l4)) >> ((15 - (i & 0xf)) << 2))) & 0xf];
290: }
291: return data;
292: }
293:
294: /**
295: * Performs the encryption/decryption of data.
296: * @param keyIndex index of the the key
297: * @param encryptMode indicates if its encryption or decryption
298: */
299: private void cipherBlock(int keyIndex, boolean encryptMode) {
300:
301: byte[] key = dkey[keyIndex];
302: byte[] data = holdData;
303:
304: int j = encryptMode ? 0 : 128 - BLOCK_SIZE;
305: int offset = (encryptMode ? 0 : 16) - BLOCK_SIZE;
306:
307: // initial permutations
308:
309: int t, v;
310: int left = 0;
311: for (int i = 0; i < 8; i++) {
312: left |= initPermLeft[(v = i << 5) + 16
313: + ((t = data[i]) & 0xf)]
314: | initPermLeft[v + ((t >> 4) & 0xf)];
315: }
316:
317: int right = 0;
318: for (int i = 0; i < 8; i++) {
319: right |= initPermRight[(v = i << 5) + 16
320: + ((t = data[i]) & 0xf)]
321: | initPermRight[v + ((t >> 4) & 0xf)];
322: }
323:
324: int i = 0;
325: while (true) {
326: // making the first bit and last bit adjacent
327: // move the first bit to the last
328: int temp = (right << 1) | ((right >> 31) & 1);
329:
330: // Mangler Function
331: // every 6 bit is fed into the sbox, which
332: // produces 4 bit output
333: left ^= s0p[(temp & 0x3f) ^ key[j]]
334: ^ s1p[((temp >> 4) & 0x3f) ^ key[j + 1]]
335: ^ s2p[((temp >> 8) & 0x3f) ^ key[j + 2]]
336: ^ s3p[((temp >> 12) & 0x3f) ^ key[j + 3]]
337: ^ s4p[((temp >> 16) & 0x3f) ^ key[j + 4]]
338: ^ s5p[((temp >> 20) & 0x3f) ^ key[j + 5]]
339: ^ s6p[((temp >> 24) & 0x3f) ^ key[j + 6]];
340:
341: // making the last sbox input last bit from right[0]
342: temp = ((right & 1) << 5) | ((right >> 27) & 0x1f);
343: left ^= s7p[temp ^ key[j + 7]];
344:
345: if (i++ == 15) {
346: break;
347: }
348:
349: temp = left;
350: left = right;
351: right = temp;
352: j -= offset;
353: }
354:
355: // permutations
356:
357: int high = perm[left & 0xf] | perm[32 + ((left >> 8) & 0xf)]
358: | perm[64 + ((left >> 16) & 0xf)]
359: | perm[96 + ((left >> 24) & 0xf)]
360: | perm[128 + (right & 0xf)]
361: | perm[160 + ((right >> 8) & 0xf)]
362: | perm[192 + ((right >> 16) & 0xf)]
363: | perm[224 + ((right >> 24) & 0xf)];
364:
365: int low = perm[16 + ((left >> 4) & 0xf)]
366: | perm[48 + ((left >> 12) & 0xf)]
367: | perm[80 + ((left >> 20) & 0xf)]
368: | perm[112 + ((left >> 28) & 0xf)]
369: | perm[144 + ((right >> 4) & 0xf)]
370: | perm[176 + ((right >> 12) & 0xf)]
371: | perm[208 + ((right >> 20) & 0xf)]
372: | perm[240 + ((right >> 28) & 0xf)];
373:
374: data[0] = (byte) low;
375: data[1] = (byte) (low >> 8);
376: data[2] = (byte) (low >> 16);
377: data[3] = (byte) (low >> 24);
378: data[4] = (byte) high;
379: data[5] = (byte) (high >> 8);
380: data[6] = (byte) (high >> 16);
381: data[7] = (byte) (high >> 24);
382: }
383:
384: /**
385: * Implements part of the DES algorithm.
386: * @param key An 8 byte array containing the key data
387: * @param keyOffset offset into the key byte array
388: * @return the result of operation
389: */
390: private static byte[] expandKey(byte[] key, int keyOffset) {
391:
392: byte ek[] = new byte[128];
393: int pos = 0;
394:
395: for (int i = 0; i < 8; i++) {
396:
397: int octet = key[keyOffset++];
398: int len;
399:
400: for (int j = 0; j < 7; j++) {
401:
402: len = expandData[pos++];
403: int offset = 0;
404:
405: if ((octet & (0x80 >> j)) != 0) {
406:
407: while (len-- > 0) {
408: int v;
409: if ((v = expandData[pos++]) == 125) {
410: offset += 16;
411: } else {
412: ek[offset += (v >> 3)] |= (1 << (v & 0x7));
413: }
414: }
415: } else {
416: pos += len;
417: }
418: }
419: }
420: return ek;
421: }
422: }
|