1 package org.bouncycastle.crypto.engines; 2 3 import org.bouncycastle.crypto.BlockCipher; 4 import org.bouncycastle.crypto.CipherParameters; 5 import org.bouncycastle.crypto.DataLengthException; 6 import org.bouncycastle.crypto.OutputLengthException; 7 import org.bouncycastle.crypto.params.KeyParameter; 8 9 /** 10 * a class that provides a basic DES engine. 11 */ 12 public class DESEngine 13 implements BlockCipher 14 { 15 protected static final int BLOCK_SIZE = 8; 16 17 private int[] workingKey = null; 18 19 /** 20 * standard constructor. 21 */ DESEngine()22 public DESEngine() 23 { 24 } 25 26 /** 27 * initialise a DES cipher. 28 * 29 * @param encrypting whether or not we are for encryption. 30 * @param params the parameters required to set up the cipher. 31 * @exception IllegalArgumentException if the params argument is 32 * inappropriate. 33 */ init( boolean encrypting, CipherParameters params)34 public void init( 35 boolean encrypting, 36 CipherParameters params) 37 { 38 if (params instanceof KeyParameter) 39 { 40 if (((KeyParameter)params).getKey().length > 8) 41 { 42 throw new IllegalArgumentException("DES key too long - should be 8 bytes"); 43 } 44 45 workingKey = generateWorkingKey(encrypting, 46 ((KeyParameter)params).getKey()); 47 48 return; 49 } 50 51 throw new IllegalArgumentException("invalid parameter passed to DES init - " + params.getClass().getName()); 52 } 53 getAlgorithmName()54 public String getAlgorithmName() 55 { 56 return "DES"; 57 } 58 getBlockSize()59 public int getBlockSize() 60 { 61 return BLOCK_SIZE; 62 } 63 processBlock( byte[] in, int inOff, byte[] out, int outOff)64 public int processBlock( 65 byte[] in, 66 int inOff, 67 byte[] out, 68 int outOff) 69 { 70 if (workingKey == null) 71 { 72 throw new IllegalStateException("DES engine not initialised"); 73 } 74 75 if ((inOff + BLOCK_SIZE) > in.length) 76 { 77 throw new DataLengthException("input buffer too short"); 78 } 79 80 if ((outOff + BLOCK_SIZE) > out.length) 81 { 82 throw new OutputLengthException("output buffer too short"); 83 } 84 85 desFunc(workingKey, in, inOff, out, outOff); 86 87 return BLOCK_SIZE; 88 } 89 reset()90 public void reset() 91 { 92 } 93 94 /** 95 * what follows is mainly taken from "Applied Cryptography", by 96 * Bruce Schneier, however it also bears great resemblance to Richard 97 * Outerbridge's D3DES... 98 */ 99 100 // private static final short[] Df_Key = 101 // { 102 // 0x01,0x23,0x45,0x67,0x89,0xab,0xcd,0xef, 103 // 0xfe,0xdc,0xba,0x98,0x76,0x54,0x32,0x10, 104 // 0x89,0xab,0xcd,0xef,0x01,0x23,0x45,0x67 105 // }; 106 107 private static final short[] bytebit = 108 { 109 0200, 0100, 040, 020, 010, 04, 02, 01 110 }; 111 112 private static final int[] bigbyte = 113 { 114 0x800000, 0x400000, 0x200000, 0x100000, 115 0x80000, 0x40000, 0x20000, 0x10000, 116 0x8000, 0x4000, 0x2000, 0x1000, 117 0x800, 0x400, 0x200, 0x100, 118 0x80, 0x40, 0x20, 0x10, 119 0x8, 0x4, 0x2, 0x1 120 }; 121 122 /* 123 * Use the key schedule specified in the Standard (ANSI X3.92-1981). 124 */ 125 126 private static final byte[] pc1 = 127 { 128 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 129 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35, 130 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 131 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3 132 }; 133 134 private static final byte[] totrot = 135 { 136 1, 2, 4, 6, 8, 10, 12, 14, 137 15, 17, 19, 21, 23, 25, 27, 28 138 }; 139 140 private static final byte[] pc2 = 141 { 142 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 143 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 144 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 145 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 146 }; 147 148 private static final int[] SP1 = { 149 0x01010400, 0x00000000, 0x00010000, 0x01010404, 150 0x01010004, 0x00010404, 0x00000004, 0x00010000, 151 0x00000400, 0x01010400, 0x01010404, 0x00000400, 152 0x01000404, 0x01010004, 0x01000000, 0x00000004, 153 0x00000404, 0x01000400, 0x01000400, 0x00010400, 154 0x00010400, 0x01010000, 0x01010000, 0x01000404, 155 0x00010004, 0x01000004, 0x01000004, 0x00010004, 156 0x00000000, 0x00000404, 0x00010404, 0x01000000, 157 0x00010000, 0x01010404, 0x00000004, 0x01010000, 158 0x01010400, 0x01000000, 0x01000000, 0x00000400, 159 0x01010004, 0x00010000, 0x00010400, 0x01000004, 160 0x00000400, 0x00000004, 0x01000404, 0x00010404, 161 0x01010404, 0x00010004, 0x01010000, 0x01000404, 162 0x01000004, 0x00000404, 0x00010404, 0x01010400, 163 0x00000404, 0x01000400, 0x01000400, 0x00000000, 164 0x00010004, 0x00010400, 0x00000000, 0x01010004 165 }; 166 167 private static final int[] SP2 = { 168 0x80108020, 0x80008000, 0x00008000, 0x00108020, 169 0x00100000, 0x00000020, 0x80100020, 0x80008020, 170 0x80000020, 0x80108020, 0x80108000, 0x80000000, 171 0x80008000, 0x00100000, 0x00000020, 0x80100020, 172 0x00108000, 0x00100020, 0x80008020, 0x00000000, 173 0x80000000, 0x00008000, 0x00108020, 0x80100000, 174 0x00100020, 0x80000020, 0x00000000, 0x00108000, 175 0x00008020, 0x80108000, 0x80100000, 0x00008020, 176 0x00000000, 0x00108020, 0x80100020, 0x00100000, 177 0x80008020, 0x80100000, 0x80108000, 0x00008000, 178 0x80100000, 0x80008000, 0x00000020, 0x80108020, 179 0x00108020, 0x00000020, 0x00008000, 0x80000000, 180 0x00008020, 0x80108000, 0x00100000, 0x80000020, 181 0x00100020, 0x80008020, 0x80000020, 0x00100020, 182 0x00108000, 0x00000000, 0x80008000, 0x00008020, 183 0x80000000, 0x80100020, 0x80108020, 0x00108000 184 }; 185 186 private static final int[] SP3 = { 187 0x00000208, 0x08020200, 0x00000000, 0x08020008, 188 0x08000200, 0x00000000, 0x00020208, 0x08000200, 189 0x00020008, 0x08000008, 0x08000008, 0x00020000, 190 0x08020208, 0x00020008, 0x08020000, 0x00000208, 191 0x08000000, 0x00000008, 0x08020200, 0x00000200, 192 0x00020200, 0x08020000, 0x08020008, 0x00020208, 193 0x08000208, 0x00020200, 0x00020000, 0x08000208, 194 0x00000008, 0x08020208, 0x00000200, 0x08000000, 195 0x08020200, 0x08000000, 0x00020008, 0x00000208, 196 0x00020000, 0x08020200, 0x08000200, 0x00000000, 197 0x00000200, 0x00020008, 0x08020208, 0x08000200, 198 0x08000008, 0x00000200, 0x00000000, 0x08020008, 199 0x08000208, 0x00020000, 0x08000000, 0x08020208, 200 0x00000008, 0x00020208, 0x00020200, 0x08000008, 201 0x08020000, 0x08000208, 0x00000208, 0x08020000, 202 0x00020208, 0x00000008, 0x08020008, 0x00020200 203 }; 204 205 private static final int[] SP4 = { 206 0x00802001, 0x00002081, 0x00002081, 0x00000080, 207 0x00802080, 0x00800081, 0x00800001, 0x00002001, 208 0x00000000, 0x00802000, 0x00802000, 0x00802081, 209 0x00000081, 0x00000000, 0x00800080, 0x00800001, 210 0x00000001, 0x00002000, 0x00800000, 0x00802001, 211 0x00000080, 0x00800000, 0x00002001, 0x00002080, 212 0x00800081, 0x00000001, 0x00002080, 0x00800080, 213 0x00002000, 0x00802080, 0x00802081, 0x00000081, 214 0x00800080, 0x00800001, 0x00802000, 0x00802081, 215 0x00000081, 0x00000000, 0x00000000, 0x00802000, 216 0x00002080, 0x00800080, 0x00800081, 0x00000001, 217 0x00802001, 0x00002081, 0x00002081, 0x00000080, 218 0x00802081, 0x00000081, 0x00000001, 0x00002000, 219 0x00800001, 0x00002001, 0x00802080, 0x00800081, 220 0x00002001, 0x00002080, 0x00800000, 0x00802001, 221 0x00000080, 0x00800000, 0x00002000, 0x00802080 222 }; 223 224 private static final int[] SP5 = { 225 0x00000100, 0x02080100, 0x02080000, 0x42000100, 226 0x00080000, 0x00000100, 0x40000000, 0x02080000, 227 0x40080100, 0x00080000, 0x02000100, 0x40080100, 228 0x42000100, 0x42080000, 0x00080100, 0x40000000, 229 0x02000000, 0x40080000, 0x40080000, 0x00000000, 230 0x40000100, 0x42080100, 0x42080100, 0x02000100, 231 0x42080000, 0x40000100, 0x00000000, 0x42000000, 232 0x02080100, 0x02000000, 0x42000000, 0x00080100, 233 0x00080000, 0x42000100, 0x00000100, 0x02000000, 234 0x40000000, 0x02080000, 0x42000100, 0x40080100, 235 0x02000100, 0x40000000, 0x42080000, 0x02080100, 236 0x40080100, 0x00000100, 0x02000000, 0x42080000, 237 0x42080100, 0x00080100, 0x42000000, 0x42080100, 238 0x02080000, 0x00000000, 0x40080000, 0x42000000, 239 0x00080100, 0x02000100, 0x40000100, 0x00080000, 240 0x00000000, 0x40080000, 0x02080100, 0x40000100 241 }; 242 243 private static final int[] SP6 = { 244 0x20000010, 0x20400000, 0x00004000, 0x20404010, 245 0x20400000, 0x00000010, 0x20404010, 0x00400000, 246 0x20004000, 0x00404010, 0x00400000, 0x20000010, 247 0x00400010, 0x20004000, 0x20000000, 0x00004010, 248 0x00000000, 0x00400010, 0x20004010, 0x00004000, 249 0x00404000, 0x20004010, 0x00000010, 0x20400010, 250 0x20400010, 0x00000000, 0x00404010, 0x20404000, 251 0x00004010, 0x00404000, 0x20404000, 0x20000000, 252 0x20004000, 0x00000010, 0x20400010, 0x00404000, 253 0x20404010, 0x00400000, 0x00004010, 0x20000010, 254 0x00400000, 0x20004000, 0x20000000, 0x00004010, 255 0x20000010, 0x20404010, 0x00404000, 0x20400000, 256 0x00404010, 0x20404000, 0x00000000, 0x20400010, 257 0x00000010, 0x00004000, 0x20400000, 0x00404010, 258 0x00004000, 0x00400010, 0x20004010, 0x00000000, 259 0x20404000, 0x20000000, 0x00400010, 0x20004010 260 }; 261 262 private static final int[] SP7 = { 263 0x00200000, 0x04200002, 0x04000802, 0x00000000, 264 0x00000800, 0x04000802, 0x00200802, 0x04200800, 265 0x04200802, 0x00200000, 0x00000000, 0x04000002, 266 0x00000002, 0x04000000, 0x04200002, 0x00000802, 267 0x04000800, 0x00200802, 0x00200002, 0x04000800, 268 0x04000002, 0x04200000, 0x04200800, 0x00200002, 269 0x04200000, 0x00000800, 0x00000802, 0x04200802, 270 0x00200800, 0x00000002, 0x04000000, 0x00200800, 271 0x04000000, 0x00200800, 0x00200000, 0x04000802, 272 0x04000802, 0x04200002, 0x04200002, 0x00000002, 273 0x00200002, 0x04000000, 0x04000800, 0x00200000, 274 0x04200800, 0x00000802, 0x00200802, 0x04200800, 275 0x00000802, 0x04000002, 0x04200802, 0x04200000, 276 0x00200800, 0x00000000, 0x00000002, 0x04200802, 277 0x00000000, 0x00200802, 0x04200000, 0x00000800, 278 0x04000002, 0x04000800, 0x00000800, 0x00200002 279 }; 280 281 private static final int[] SP8 = { 282 0x10001040, 0x00001000, 0x00040000, 0x10041040, 283 0x10000000, 0x10001040, 0x00000040, 0x10000000, 284 0x00040040, 0x10040000, 0x10041040, 0x00041000, 285 0x10041000, 0x00041040, 0x00001000, 0x00000040, 286 0x10040000, 0x10000040, 0x10001000, 0x00001040, 287 0x00041000, 0x00040040, 0x10040040, 0x10041000, 288 0x00001040, 0x00000000, 0x00000000, 0x10040040, 289 0x10000040, 0x10001000, 0x00041040, 0x00040000, 290 0x00041040, 0x00040000, 0x10041000, 0x00001000, 291 0x00000040, 0x10040040, 0x00001000, 0x00041040, 292 0x10001000, 0x00000040, 0x10000040, 0x10040000, 293 0x10040040, 0x10000000, 0x00040000, 0x10001040, 294 0x00000000, 0x10041040, 0x00040040, 0x10000040, 295 0x10040000, 0x10001000, 0x10001040, 0x00000000, 296 0x10041040, 0x00041000, 0x00041000, 0x00001040, 297 0x00001040, 0x00040040, 0x10000000, 0x10041000 298 }; 299 300 /** 301 * generate an integer based working key based on our secret key 302 * and what we processing we are planning to do. 303 * 304 * Acknowledgements for this routine go to James Gillogly & Phil Karn. 305 * (whoever, and wherever they are!). 306 */ generateWorkingKey( boolean encrypting, byte[] key)307 protected int[] generateWorkingKey( 308 boolean encrypting, 309 byte[] key) 310 { 311 int[] newKey = new int[32]; 312 boolean[] pc1m = new boolean[56], 313 pcr = new boolean[56]; 314 315 for (int j = 0; j < 56; j++) 316 { 317 int l = pc1[j]; 318 319 pc1m[j] = ((key[l >>> 3] & bytebit[l & 07]) != 0); 320 } 321 322 for (int i = 0; i < 16; i++) 323 { 324 int l, m, n; 325 326 if (encrypting) 327 { 328 m = i << 1; 329 } 330 else 331 { 332 m = (15 - i) << 1; 333 } 334 335 n = m + 1; 336 newKey[m] = newKey[n] = 0; 337 338 for (int j = 0; j < 28; j++) 339 { 340 l = j + totrot[i]; 341 if (l < 28) 342 { 343 pcr[j] = pc1m[l]; 344 } 345 else 346 { 347 pcr[j] = pc1m[l - 28]; 348 } 349 } 350 351 for (int j = 28; j < 56; j++) 352 { 353 l = j + totrot[i]; 354 if (l < 56) 355 { 356 pcr[j] = pc1m[l]; 357 } 358 else 359 { 360 pcr[j] = pc1m[l - 28]; 361 } 362 } 363 364 for (int j = 0; j < 24; j++) 365 { 366 if (pcr[pc2[j]]) 367 { 368 newKey[m] |= bigbyte[j]; 369 } 370 371 if (pcr[pc2[j + 24]]) 372 { 373 newKey[n] |= bigbyte[j]; 374 } 375 } 376 } 377 378 // 379 // store the processed key 380 // 381 for (int i = 0; i != 32; i += 2) 382 { 383 int i1, i2; 384 385 i1 = newKey[i]; 386 i2 = newKey[i + 1]; 387 388 newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) 389 | ((i2 & 0x00fc0000) >>> 10) | ((i2 & 0x00000fc0) >>> 6); 390 391 newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) 392 | ((i2 & 0x0003f000) >>> 4) | (i2 & 0x0000003f); 393 } 394 395 return newKey; 396 } 397 398 /** 399 * the DES engine. 400 */ desFunc( int[] wKey, byte[] in, int inOff, byte[] out, int outOff)401 protected void desFunc( 402 int[] wKey, 403 byte[] in, 404 int inOff, 405 byte[] out, 406 int outOff) 407 { 408 int work, right, left; 409 410 left = (in[inOff + 0] & 0xff) << 24; 411 left |= (in[inOff + 1] & 0xff) << 16; 412 left |= (in[inOff + 2] & 0xff) << 8; 413 left |= (in[inOff + 3] & 0xff); 414 415 right = (in[inOff + 4] & 0xff) << 24; 416 right |= (in[inOff + 5] & 0xff) << 16; 417 right |= (in[inOff + 6] & 0xff) << 8; 418 right |= (in[inOff + 7] & 0xff); 419 420 work = ((left >>> 4) ^ right) & 0x0f0f0f0f; 421 right ^= work; 422 left ^= (work << 4); 423 work = ((left >>> 16) ^ right) & 0x0000ffff; 424 right ^= work; 425 left ^= (work << 16); 426 work = ((right >>> 2) ^ left) & 0x33333333; 427 left ^= work; 428 right ^= (work << 2); 429 work = ((right >>> 8) ^ left) & 0x00ff00ff; 430 left ^= work; 431 right ^= (work << 8); 432 right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff; 433 work = (left ^ right) & 0xaaaaaaaa; 434 left ^= work; 435 right ^= work; 436 left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff; 437 438 for (int round = 0; round < 8; round++) 439 { 440 int fval; 441 442 work = (right << 28) | (right >>> 4); 443 work ^= wKey[round * 4 + 0]; 444 fval = SP7[ work & 0x3f]; 445 fval |= SP5[(work >>> 8) & 0x3f]; 446 fval |= SP3[(work >>> 16) & 0x3f]; 447 fval |= SP1[(work >>> 24) & 0x3f]; 448 work = right ^ wKey[round * 4 + 1]; 449 fval |= SP8[ work & 0x3f]; 450 fval |= SP6[(work >>> 8) & 0x3f]; 451 fval |= SP4[(work >>> 16) & 0x3f]; 452 fval |= SP2[(work >>> 24) & 0x3f]; 453 left ^= fval; 454 work = (left << 28) | (left >>> 4); 455 work ^= wKey[round * 4 + 2]; 456 fval = SP7[ work & 0x3f]; 457 fval |= SP5[(work >>> 8) & 0x3f]; 458 fval |= SP3[(work >>> 16) & 0x3f]; 459 fval |= SP1[(work >>> 24) & 0x3f]; 460 work = left ^ wKey[round * 4 + 3]; 461 fval |= SP8[ work & 0x3f]; 462 fval |= SP6[(work >>> 8) & 0x3f]; 463 fval |= SP4[(work >>> 16) & 0x3f]; 464 fval |= SP2[(work >>> 24) & 0x3f]; 465 right ^= fval; 466 } 467 468 right = (right << 31) | (right >>> 1); 469 work = (left ^ right) & 0xaaaaaaaa; 470 left ^= work; 471 right ^= work; 472 left = (left << 31) | (left >>> 1); 473 work = ((left >>> 8) ^ right) & 0x00ff00ff; 474 right ^= work; 475 left ^= (work << 8); 476 work = ((left >>> 2) ^ right) & 0x33333333; 477 right ^= work; 478 left ^= (work << 2); 479 work = ((right >>> 16) ^ left) & 0x0000ffff; 480 left ^= work; 481 right ^= (work << 16); 482 work = ((right >>> 4) ^ left) & 0x0f0f0f0f; 483 left ^= work; 484 right ^= (work << 4); 485 486 out[outOff + 0] = (byte)((right >>> 24) & 0xff); 487 out[outOff + 1] = (byte)((right >>> 16) & 0xff); 488 out[outOff + 2] = (byte)((right >>> 8) & 0xff); 489 out[outOff + 3] = (byte)(right & 0xff); 490 out[outOff + 4] = (byte)((left >>> 24) & 0xff); 491 out[outOff + 5] = (byte)((left >>> 16) & 0xff); 492 out[outOff + 6] = (byte)((left >>> 8) & 0xff); 493 out[outOff + 7] = (byte)(left & 0xff); 494 } 495 } 496