KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > knowgate > misc > TEA


1 package com.knowgate.misc;
2
3 import java.math.*;
4
5 /**
6 * Tiny Encryption Algorithm.
7 * <P>
8 * (The following description is from the web page for the C and Assembler source
9 * code at <A HREF="http://vader.brad.ac.uk/tea/tea.shtml"> University of Bradford
10 * Yorkshire, England - The Cryptography & Computer Communications Security
11 * Group</A>) The description is used with the permission of the authors,
12 * Dr S J Shepherd and D A G Gillies.
13 * <P>
14 * The Tiny Encryption Algorithm is one of the fastest and most efficient
15 * cryptographic algorithms in existence. It was developed by David
16 * Wheeler and Roger Needham at the Computer Laboratory of Cambridge
17 * University. It is a Feistel cipher which uses operations from mixed
18 * (orthogonal) algebraic groups - XORs and additions in this case. It
19 * encrypts 64 data bits at a time using a 128-bit key. It seems highly
20 * resistant to differential cryptanalysis, and achieves complete
21 * diffusion (where a one bit difference in the plaintext will cause
22 * approximately 32 bit differences in the ciphertext) after only six
23 * rounds. Performance on a modern desktop computer or workstation is
24 * very impressive.
25 * <P>
26 * TEA takes 64 bits of data in v[0] and v[1], and 128 bits of key in
27 * k[0] - k[3]. The result is returned in w[0] and w[1]. Returning the
28 * result separately makes implementation of cipher modes other than
29 * Electronic Code Book a little bit easier.
30 * <P>
31 * TEA can be operated in any of the modes of DES.
32 * <P>
33 * n is the number of iterations. 32 is ample, 16 is sufficient, as few
34 * as eight should be OK for most applications, especially ones where
35 * the data age quickly (real-time video, for example). The algorithm
36 * achieves good dispersion after six iterations. The iteration count
37 * can be made variable if required.
38 * <P>
39 * Note this algorithm is optimised for 32-bit CPUs with fast shift
40 * capabilities. It can very easily be ported to assembly language on
41 * most CPUs.
42 * <P>
43 * delta is chosen to be the Golden ratio ((5/4)1/2 - 1/2 ~ 0.618034)
44 * multiplied by 232. On entry to decipher(), sum is set to be delta *
45 * n. Which way round you call the functions is arbitrary: DK(EK(P)) =
46 * EK(DK(P)) where EK and DK are encryption and decryption under key K
47 * respectively.
48 * <P>
49 * Translator's notes:
50 * <UL>
51 * <LI> Although the <I>this algorithm is optimised for
52 * 32-bit CPUs with fast shift capabilities</I> Java manages to throw
53 * it all away by not providing unsigned values resulting in the excessive
54 * use of AND's to prevent sign extension on promotion of a byte
55 * to an integer.
56 * </LI>
57 * <P>
58 * <LI>
59 * The following description is taken from the
60 * Mach5 Software cryptography archives at
61 * <A HREF="http://www.mach5.com/crypto/">www.mach5.com/crypto</A>.
62 * <p><font face="Arial" size="4">Tiny Encryption Algorithm (TEA)</font><br>
63 * <font size="3" face="Arial">TEA is a cryptographic algorithm designed to minimize memory
64 * footprint, and maximize speed. However, the cryptographers from <a
65 *
66 * HREF="http://www.counterpane.com">Counterpane Systems</a> have <a
67 *
68 * HREF="http://www.cs.berkeley.edu/~daw/keysched-crypto96.ps">discovered three related-key
69 * attacks </a>on TEA, the best of which requires only 223 chosen plaintexts and one related
70 * key query. The problems arise from the overly simple key schedule. Each TEA key can be
71 * found to have three other equivalent keys, as described in <a
72 *
73 * HREF="http://www.cs.berkeley.edu/~daw/keysched-icics97.ps">a paper</a> by <a
74 *
75 * HREF="http://www.cs.berkeley.edu/~daw/">David Wagner</a>, John Kelsey, and <a
76 *
77 * HREF="http://www.counterpane.com/schneier.html">Bruce Schneier</a>. This precludes the
78 * possibility of using TEA as a hash function. Roger Needham and David Wheeler have proposed
79 * <a HREF="http://www.cl.cam.ac.uk/ftp/users/djw3/xtea.ps">extensions to TEA</a> that
80 * counters the above attacks.</font></p>
81 * </LI>
82 * </UL>
83 *
84 * <P> Example of use:
85 * <PRE>
86 * byte key[] = new BigInteger("39e858f86df9b909a8c87cb8d9ad599", 16).toByteArray();
87 * TEA t = new TEA(key);
88 * <BR>
89 * String src = "hello world!";
90 * System.out.println("input = " + src);
91 * byte plainSource[] = src.getBytes();
92 * int enc[] = t.encode(plainSource, plainSource.length);
93 * System.out.println(t.padding() + " bytes added as padding.");
94 * byte dec[] = t.decode(enc);
95 * System.out.println("output = " + new String(dec));
96 * </PRE>
97 *
98 * @author Translated by Michael Lecuyer (mjl@theorem.com) from the C Language.
99 * @version 1.0 Sep 8, 1998
100 * @since JDK1.1
101 */

102
103 public class TEA
104 {
105    private int _key[]; // The 128 bit key.
106
private byte _keyBytes[]; // original key as found
107
private int _padding; // amount of padding added in byte --> integer conversion.
108

109    /**
110    * Encodes and decodes "Hello world!" for your personal pleasure.
111    */

112    public static void main(String JavaDoc args[])
113    {
114       // A simple test of TEA.
115

116       byte key[] = new BigInteger("39e858f86df9b909a8c87cb8d9ad599", 16).toByteArray();
117       TEA t = new TEA(key);
118
119       String JavaDoc src = "hello world!";
120       System.out.println("input = " + src);
121       byte plainSource[] = src.getBytes();
122       int enc[] = t.encode(plainSource, plainSource.length);
123       System.out.println(t.padding() + " bytes added as padding.");
124       byte dec[] = t.decode(enc);
125       System.out.println("output = " + new String JavaDoc(dec));
126    }
127
128    /**
129    * Accepts key for enciphering/deciphering.
130    *
131    * @throws ArrayIndexOutOfBoundsException if the key isn't the correct length.
132    *
133    * @param key 128 bit (16 byte) key.
134    */

135    public TEA(byte key[])
136    {
137       int klen = key.length;
138       _key = new int[4];
139
140       // Incorrect key length throws exception.
141
if (klen != 16)
142          throw new ArrayIndexOutOfBoundsException JavaDoc(this.getClass().getName() + ": Key is not 16 bytes");
143
144       int j, i;
145       for (i = 0, j = 0; j < klen; j += 4, i++)
146          _key[i] = (key[j] << 24 ) | (((key[j+1])&0xff) << 16) | (((key[j+2])&0xff) << 8) | ((key[j+3])&0xff);
147
148       _keyBytes = key; // save for toString.
149
}
150
151    /**
152    * Representation of TEA class
153    */

154    public String JavaDoc toString()
155    {
156       String JavaDoc tea = this.getClass().getName();
157       tea += ": Tiny Encryption Algorithm (TEA) key: " + dumpBytes(_keyBytes);
158       return tea;
159    }
160
161    /**
162    * Encipher two <code>int</code>s.
163    * Replaces the original contents of the parameters with the results.
164    * The integers are usually created from 8 bytes.
165    * The usual way to collect bytes to the int array is:
166    * <PRE>
167    * byte ba[] = { .... };
168    * int v[] = new int[2];
169    * v[0] = (ba[j] << 24 ) | (((ba[j+1])&0xff) << 16) | (((ba[j+2])&0xff) << 8) | ((ba[j+3])&0xff);
170    * v[1] = (ba[j+4] << 24 ) | (((ba[j+5])&0xff) << 16) | (((ba[j+6])&0xff) << 8) | ((ba[j+7])&0xff);
171    * v = encipher(v);
172    * </PRE>
173    *
174    * @param v two <code>int</code> array as input.
175    *
176    * @return array of two <code>int</code>s, enciphered.
177    */

178    public int [] encipher(int v[])
179    {
180       int y=v[0];
181       int z=v[1];
182       int sum=0;
183       int delta=0x9E3779B9;
184       int a=_key[0];
185       int b=_key[1];
186       int c=_key[2];
187       int d=_key[3];
188       int n=32;
189
190       while(n-->0)
191       {
192          sum += delta;
193          y += (z << 4)+a ^ z+sum ^ (z >> 5)+b;
194          z += (y << 4)+c ^ y+sum ^ (y >> 5)+d;
195       }
196
197       v[0] = y;
198       v[1] = z;
199
200       return v;
201    }
202
203    /**
204    * Decipher two <code>int</code>s.
205    * Replaces the original contents of the parameters with the results.
206    * The integers are usually decocted to 8 bytes.
207    * The decoction of the <code>int</code>s to bytes can be done
208    * this way.
209    * <PRE>
210    * int x[] = decipher(ins);
211    * outb[j] = (byte)(x[0] >>> 24);
212    * outb[j+1] = (byte)(x[0] >>> 16);
213    * outb[j+2] = (byte)(x[0] >>> 8);
214    * outb[j+3] = (byte)(x[0]);
215    * outb[j+4] = (byte)(x[1] >>> 24);
216    * outb[j+5] = (byte)(x[1] >>> 16);
217    * outb[j+6] = (byte)(x[1] >>> 8);
218    * outb[j+7] = (byte)(x[1]);
219    * </PRE>
220    *
221    * @param v <code>int</code> array of 2
222    *
223    * @return deciphered <code>int</code> array of 2
224    */

225    public int [] decipher(int v[])
226    {
227       int y=v[0];
228       int z=v[1];
229       int sum=0xC6EF3720;
230       int delta=0x9E3779B9;
231       int a=_key[0];
232       int b=_key[1];
233       int c=_key[2];
234       int d=_key[3];
235       int n=32;
236
237       // sum = delta<<5, in general sum = delta * n
238

239       while(n-->0)
240       {
241          z -= (y << 4)+c ^ y+sum ^ (y >> 5) + d;
242          y -= (z << 4)+a ^ z+sum ^ (z >> 5) + b;
243          sum -= delta;
244       }
245
246       v[0] = y;
247       v[1] = z;
248
249       return v;
250    }
251
252    /**
253    * Encipher two <code>bytes</code>s.
254    *
255    * @param v <code>byte</code> array of 2
256    *
257    * @return enciphered <code>byte</code> array of 2
258    */

259    public byte [] encipher(byte v[])
260    {
261       byte y=v[0];
262       byte z=v[1];
263       int sum=0;
264       int delta=0x9E3779B9;
265       int a=_key[0];
266       int b=_key[1];
267       int c=_key[2];
268       int d=_key[3];
269       int n=32;
270
271       while(n-->0)
272       {
273          sum += delta;
274          y += (z << 4)+a ^ z+sum ^ (z >> 5)+b;
275          z += (y << 4)+c ^ y+sum ^ (y >> 5)+d;
276       }
277
278       v[0] = y;
279       v[1] = z;
280
281       return v;
282    }
283
284    /**
285    * Decipher two <code>bytes</code>s.
286    *
287    * @param v <code>byte</code> array of 2
288    *
289    * @return decipherd <code>byte</code> array of 2
290    */

291    public byte [] decipher(byte v[])
292    {
293       byte y=v[0];
294       byte z=v[1];
295       int sum=0xC6EF3720;
296       int delta=0x9E3779B9;
297       int a=_key[0];
298       int b=_key[1];
299       int c=_key[2];
300       int d=_key[3];
301       int n=32;
302
303       // sum = delta<<5, in general sum = delta * n
304

305       while(n-->0)
306       {
307          z -= (y << 4)+c ^ y+sum ^ (y >> 5)+d;
308          y -= (z << 4)+a ^ z+sum ^ (z >> 5)+b;
309          sum -= delta;
310       }
311
312       v[0] = y;
313       v[1] = z;
314
315       return v;
316    }
317
318    /**
319    * Byte wrapper for encoding.
320    * Converts bytes to ints.
321    * Padding will be added if required.
322    *
323    * @param b incoming <code>byte</code> array
324    *
325    * @param byte count
326    *
327    * @return integer conversion array, possibly with padding.
328    *
329    * @see #padding
330    */

331    public int [] encode(byte b[], int count)
332    {
333       int j ,i;
334       int bLen = count;
335       byte bp[] = b;
336
337       _padding = bLen % 8;
338       if (_padding != 0) // Add some padding, if necessary.
339
{
340          _padding = 8 - (bLen % 8);
341          bp = new byte[bLen + _padding];
342          System.arraycopy(b, 0, bp, 0, bLen);
343          bLen = bp.length;
344       }
345
346       int intCount = bLen / 4;
347       int r[] = new int[2];
348       int out[] = new int[intCount];
349
350       for (i = 0, j = 0; j < bLen; j += 8, i += 2)
351       {
352          // Java's unforgivable lack of unsigneds causes more bit
353
// twiddling than this language really needs.
354
r[0] = (bp[j] << 24 ) | (((bp[j+1])&0xff) << 16) | (((bp[j+2])&0xff) << 8) | ((bp[j+3])&0xff);
355          r[1] = (bp[j+4] << 24 ) | (((bp[j+5])&0xff) << 16) | (((bp[j+6])&0xff) << 8) | ((bp[j+7])&0xff);
356          encipher(r);
357          out[i] = r[0];
358          out[i+1] = r[1];
359       }
360
361       return out;
362    }
363
364    /**
365    * Report how much padding was done in the last encode.
366    *
367    * @return bytes of padding added
368    *
369    * @see #encode
370    */

371    public int padding()
372    {
373       return _padding;
374    }
375
376    /**
377    * Convert a byte array to ints and then decode.
378    * There may be some padding at the end of the byte array from
379    * the previous encode operation.
380    *
381    * @param b bytes to decode
382    * @param count number of bytes in the array to decode
383    *
384    * @return <code>byte</code> array of decoded bytes.
385    */

386    public byte [] decode(byte b[], int count)
387    {
388       int i, j;
389
390       int intCount = count / 4;
391       int ini[] = new int[intCount];
392       for (i = 0, j = 0; i < intCount; i += 2, j += 8)
393       {
394          ini[i] = (b[j] << 24 ) | (((b[j+1])&0xff) << 16) | (((b[j+2])&0xff) << 8) | ((b[j+3])&0xff);
395          ini[i+1] = (b[j+4] << 24 ) | (((b[j+5])&0xff) << 16) | (((b[j+6])&0xff) << 8) | ((b[j+7])&0xff);
396       }
397       return decode(ini);
398    }
399
400    /**
401    * Decode an integer array.
402    * There may be some padding at the end of the byte array from
403    * the previous encode operation.
404    *
405    * @param b bytes to decode
406    * @param count number of bytes in the array to decode
407    *
408    * @return <code>byte</code> array of decoded bytes.
409    */

410    public byte [] decode(int b[])
411    {
412       // create the large number and start stripping ints out, two at a time.
413
int intCount = b.length;
414
415       byte outb[] = new byte[intCount * 4];
416       int tmp[] = new int[2];
417
418       // decipher all the ints.
419
int i, j;
420       for (j = 0, i = 0; i < intCount; i += 2, j += 8)
421       {
422          tmp[0] = b[i];
423          tmp[1] = b[i+1];
424          decipher(tmp);
425          outb[j] = (byte)(tmp[0] >>> 24);
426          outb[j+1] = (byte)(tmp[0] >>> 16);
427          outb[j+2] = (byte)(tmp[0] >>> 8);
428          outb[j+3] = (byte)(tmp[0]);
429          outb[j+4] = (byte)(tmp[1] >>> 24);
430          outb[j+5] = (byte)(tmp[1] >>> 16);
431          outb[j+6] = (byte)(tmp[1] >>> 8);
432          outb[j+7] = (byte)(tmp[1]);
433       }
434
435       return outb;
436    }
437
438
439    // Display some bytes in HEX.
440
//
441
private String JavaDoc dumpBytes(byte b[])
442    {
443       StringBuffer JavaDoc r = new StringBuffer JavaDoc();
444       final String JavaDoc hex = "0123456789ABCDEF";
445
446       for (int i = 0; i < b.length; i++)
447       {
448          int c = ((b[i]) >>> 4) & 0xf;
449          r.append(hex.charAt(c));
450          c = ((int)b[i] & 0xf);
451          r.append(hex.charAt(c));
452       }
453
454       return r.toString();
455    }
456
457 }
458
Popular Tags