Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: mindbright/security/IDEA.java


1   /******************************************************************************
2    *
3    * Copyright (c) 1998,99 by Mindbright Technology AB, Stockholm, Sweden.
4    *                 www.mindbright.se, info@mindbright.se
5    *
6    * This program is free software; you can redistribute it and/or modify
7    * it under the terms of the GNU General Public License as published by
8    * the Free Software Foundation; either version 2 of the License, or
9    * (at your option) any later version.
10   *
11   * This program is distributed in the hope that it will be useful,
12   * but WITHOUT ANY WARRANTY; without even the implied warranty of
13   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14   * GNU General Public License for more details.
15   *
16   *****************************************************************************
17   * $Author: nallen $
18   * $Date: 2001/11/12 16:31:15 $
19   * $Name:  $
20   *****************************************************************************/
21  /*
22   * !!! Author's comment: The contents of this file is heavily based
23   * upon Tatu Ylonen's c-code (from the ssh1 package). His comments follows:
24   * ...
25   * This code is based on Xuejia Lai: On the Design and Security of Block
26   * Ciphers, ETH Series in Information Processing, vol. 1, Hartung-Gorre
27   * Verlag, Konstanz, Switzerland, 1992.  Another source was Bruce
28   * Schneier: Applied Cryptography, John Wiley & Sons, 1994.
29   *
30   * The IDEA mathematical formula may be covered by one or more of the
31   * following patents: PCT/CH91/00117, EP 0 482 154 B1, US Pat. 5,214,703.
32   */
33  
34  package mindbright.security;
35  
36  import java.math.BigInteger;
37  
38  public final class IDEA extends Cipher {
39  
40    protected int[]   key_schedule = new int[52];
41    protected int     IV0 = 0;
42    protected int     IV1 = 0;
43  
44    public synchronized void encrypt(byte[] src, int srcOff, byte[] dest, int destOff, int len) {
45      int[]  out = new int[2];
46      int iv0 = IV0;
47      int iv1 = IV1;
48      int end = srcOff + len;
49  
50      for(int si = srcOff, di = destOff; si < end; si += 8, di += 8) {
51        encrypt(iv0, iv1, out);
52        iv0 = out[0];
53        iv1 = out[1];
54        iv0 ^= ((src[si + 3] & 0xff) | ((src[si + 2] & 0xff) << 8) |
55          ((src[si + 1] & 0xff) << 16) | ((src[si] & 0xff) << 24));
56        iv1 ^= ((src[si + 7] & 0xff) | ((src[si + 6] & 0xff) << 8) |
57          ((src[si + 5] & 0xff) << 16) | ((src[si + 4] & 0xff) << 24));
58  
59        if(di + 8 <= end) {
60      dest[di+3] = (byte)( iv0         & 0xff);
61      dest[di+2] = (byte)((iv0 >>> 8 ) & 0xff);
62      dest[di+1] = (byte)((iv0 >>> 16) & 0xff);
63      dest[di]   = (byte)((iv0 >>> 24) & 0xff);
64      dest[di+7] = (byte)( iv1         & 0xff);
65      dest[di+6] = (byte)((iv1 >>> 8 ) & 0xff);
66      dest[di+5] = (byte)((iv1 >>> 16) & 0xff);
67      dest[di+4] = (byte)((iv1 >>> 24) & 0xff);
68        } else {
69      switch(end - di) {
70      case 7:
71          dest[di+6] = (byte)((iv1 >>> 8) & 0xff);
72      case 6:
73          dest[di+5] = (byte)((iv1 >>> 16) & 0xff);
74      case 5:
75          dest[di+4] = (byte)((iv1 >>> 24) & 0xff);
76      case 4:
77          dest[di+3] = (byte)( iv0         & 0xff);
78      case 3:
79          dest[di+2] = (byte)((iv0 >>> 8) & 0xff);
80      case 2:
81          dest[di+1] = (byte)((iv0 >>> 16) & 0xff);
82      case 1:
83          dest[di]   = (byte)((iv0 >>> 24) & 0xff);
84      }
85        }
86      }
87      IV0 = iv0;
88      IV1 = iv1;
89    }
90  
91    public synchronized void decrypt(byte[] src, int srcOff, byte[] dest, int destOff, int len) {
92      int[]  out = new int[2];
93      int iv0 = IV0;
94      int iv1 = IV1;
95      int plain0, plain1;
96      int end = srcOff + len;
97  
98      for(int si = srcOff, di = destOff; si < end; si += 8, di += 8) {
99        decrypt(iv0, iv1, out);
100       iv0 = ((src[si + 3] & 0xff) | ((src[si + 2] & 0xff) << 8) |
101         ((src[si + 1] & 0xff) << 16) | ((src[si] & 0xff) << 24));
102       iv1 = ((src[si + 7] & 0xff) | ((src[si + 6] & 0xff) << 8) |
103         ((src[si + 5] & 0xff) << 16) | ((src[si + 4] & 0xff) << 24));
104       plain0 = out[0] ^ iv0;
105       plain1 = out[1] ^ iv1;
106 
107       if(di + 8 <= end) {
108     dest[di+3] = (byte)( plain0         & 0xff);
109     dest[di+2] = (byte)((plain0 >>> 8 ) & 0xff);
110     dest[di+1] = (byte)((plain0 >>> 16) & 0xff);
111     dest[di]   = (byte)((plain0 >>> 24) & 0xff);
112     dest[di+7] = (byte)( plain1         & 0xff);
113     dest[di+6] = (byte)((plain1 >>> 8 ) & 0xff);
114     dest[di+5] = (byte)((plain1 >>> 16) & 0xff);
115     dest[di+4] = (byte)((plain1 >>> 24) & 0xff);
116       } else {
117     switch(end - di) {
118     case 7:
119         dest[di+6] = (byte)((plain1 >>> 8) & 0xff);
120     case 6:
121         dest[di+5] = (byte)((plain1 >>> 16) & 0xff);
122     case 5:
123         dest[di+4] = (byte)((plain1 >>> 24) & 0xff);
124     case 4:
125         dest[di+3] = (byte)( plain0         & 0xff);
126     case 3:
127         dest[di+2] = (byte)((plain0 >>> 8) & 0xff);
128     case 2:
129         dest[di+1] = (byte)((plain0 >>> 16) & 0xff);
130     case 1:
131         dest[di]   = (byte)((plain0 >>> 24) & 0xff);
132     }
133       }
134     }
135     IV0 = iv0;
136     IV1 = iv1;
137   }
138 
139   public void setKey(byte[] key) {
140       int i, ki = 0, j = 0;
141       for(i = 0; i < 8; i++)
142     key_schedule[i] = ((key[2 * i] & 0xff) << 8) | (key[(2 * i) + 1] & 0xff);
143 
144       for(i = 8, j = 0; i < 52; i++) {
145     j++;
146     key_schedule[ki + j + 7] = ((key_schedule[ki + (j & 7)] << 9) |
147               (key_schedule[ki + ((j + 1) & 7)] >>> 7)) & 0xffff;
148     ki += j & 8;
149     j &= 7;
150       }
151   }
152 
153   public final void encrypt(int l, int r, int[] out) {
154       int t1 = 0, t2 = 0, x1, x2, x3, x4, ki = 0;
155 
156       x1 = (l >>> 16);
157       x2 = (l & 0xffff);
158       x3 = (r >>> 16);
159       x4 = (r & 0xffff);
160 
161       for(int round = 0; round < 8; round++) {
162     x1 = mulop(x1 & 0xffff, key_schedule[ki++]);
163     x2 = (x2 + key_schedule[ki++]);
164     x3 = (x3 + key_schedule[ki++]);
165     x4 = mulop(x4 & 0xffff, key_schedule[ki++]);
166 
167     t1 = (x1 ^ x3);
168     t2 = (x2 ^ x4);
169     t1 = mulop(t1 & 0xffff, key_schedule[ki++]);
170     t2 = (t1 + t2);
171     t2 = mulop(t2 & 0xffff, key_schedule[ki++]);
172     t1 = (t1 + t2);
173 
174     x1 = (x1 ^ t2);
175     x4 = (x4 ^ t1);
176     t1 = (t1 ^ x2);
177     x2 = (t2 ^ x3);
178     x3 = t1;
179       }
180   
181       t2 = x2;
182       x1 = mulop(x1 & 0xffff, key_schedule[ki++]);
183       x2 = (t1 + key_schedule[ki++]);
184       x3 = ((t2 + key_schedule[ki++]) & 0xffff);
185       x4 = mulop(x4 & 0xffff, key_schedule[ki]);
186 
187 
188       out[0] = (x1 << 16) | (x2 & 0xffff);
189       out[1] = (x3 << 16) | (x4 & 0xffff);
190   }
191 
192   public final void decrypt(int l, int r, int[] out) {
193       encrypt(l, r, out);
194   }
195 
196   public static final int mulop(int a, int b) {
197       int ab = a * b;
198       if(ab != 0) {
199     int lo = ab & 0xffff;
200     int hi = (ab >>> 16) & 0xffff;
201     return ((lo - hi) + ((lo < hi) ? 1 : 0));
202       }
203       if(a == 0)
204     return (1 - b);
205       return  (1 - a);
206   }
207 
208     /* !!! REMOVE DEBUG !!!
209 
210   public static void main(String[] argv) {
211     byte[] key = { 
212       (byte)0xd3, (byte)0x96, (byte)0xcf, (byte)0x07, (byte)0xfa, (byte)0xa2, (byte)0x64,
213       (byte)0xfe, (byte)0xf3, (byte)0xa2, (byte)0x06, (byte)0x07, (byte)0x1a, (byte)0xb6,
214       (byte)0x13, (byte)0xf6
215     };
216 
217     byte[] txt = {
218       (byte)0x2e, (byte)0xbe, (byte)0xc5, (byte)0xac, (byte)0x02, (byte)0xa1, (byte)0xd5, 
219       (byte)0x7f, (byte)0x01, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x1f, (byte)0x43, 
220       (byte)0x6f, (byte)0x72, (byte)0x72, (byte)0x75, (byte)0x70, (byte)0x74, (byte)0x65, 
221       (byte)0x64, (byte)0x20, (byte)0x63, (byte)0x68, (byte)0x65, (byte)0x63, (byte)0x6b, 
222       (byte)0x20, (byte)0x62, (byte)0x79, (byte)0x74, (byte)0x65, (byte)0x73, (byte)0x20, 
223       (byte)0x6f, (byte)0x6e, (byte)0x20, (byte)0x69, (byte)0x6e, (byte)0x70, (byte)0x75, 
224       (byte)0x74, (byte)0x2e, (byte)0x91, (byte)0x9a, (byte)0x57, (byte)0xdd
225     };
226 
227     byte[] enc;
228     byte[] dec;
229 
230     System.out.println("key: " + printHex(key));
231     System.out.println("txt: " + printHex(txt));
232 
233     IDEA cipher = new IDEA();
234     cipher.setKey(key);
235 
236     for(int i = 0; i < 52; i++) {
237   if((i & 0x7) == 0)
238       System.out.println("");
239   System.out.print(" " + cipher.key_schedule[i]);
240     }
241 
242     enc = cipher.encrypt(txt);
243     System.out.println("enc: " + printHex(enc));
244 
245     cipher = new IDEA();
246     cipher.setKey(key);
247     dec = cipher.decrypt(enc);
248 
249     System.out.println("dec: " + printHex(dec));
250   }
251 
252   static String printHex(byte[] buf) {
253     byte[] out = new byte[buf.length + 1];
254     out[0] = 0;
255     System.arraycopy(buf, 0, out, 1, buf.length);
256     BigInteger big = new BigInteger(out);
257     return big.toString(16);
258   }
259 
260     */
261 
262 }
263