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