4 * An Actionscript 3 implementation of the Data Encryption Standard (DES)
\r
5 * Copyright (c) 2007 Henri Torgemane
\r
8 * The Bouncy Castle Crypto package,
\r
9 * Copyright (c) 2000-2004 The Legion Of The Bouncy Castle
\r
10 * (http://www.bouncycastle.org)
\r
12 * See LICENSE.txt for full license information.
\r
14 package com.hurlant.crypto.symmetric
\r
16 import flash.utils.ByteArray;
\r
17 import com.hurlant.util.Hex;
\r
18 import com.hurlant.util.Memory;
\r
20 public class DESKey implements ISymmetricKey
\r
23 * what follows is mainly taken from "Applied Cryptography", by Bruce
\r
24 * Schneier, however it also bears great resemblance to Richard
\r
25 * Outerbridge's D3DES...
\r
28 private static const Df_Key:Array = [ 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32,
\r
29 0x10, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23, 0x45, 0x67 ];
\r
31 private static const bytebit:Array = [ 128, 64, 32, 16, 8, 4, 2, 1 ];
\r
33 private static const bigbyte:Array = [ 0x800000, 0x400000, 0x200000, 0x100000, 0x80000, 0x40000, 0x20000, 0x10000, 0x8000,
\r
34 0x4000, 0x2000, 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1 ];
\r
37 * Use the key schedule specified in the Standard (ANSI X3.92-1981).
\r
40 private static const pc1:Array = [ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17, 9, 1, 58, 50, 42, 34, 26, 18, 10, 2,
\r
41 59, 51, 43, 35, 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21, 13, 5, 60, 52, 44, 36, 28, 20, 12,
\r
44 private static const totrot:Array = [ 1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28 ];
\r
46 private static const pc2:Array = [ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9, 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1, 40,
\r
47 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47, 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31 ];
\r
49 private static const SP1:Array = [ 0x01010400, 0x00000000, 0x00010000, 0x01010404, 0x01010004, 0x00010404, 0x00000004,
\r
50 0x00010000, 0x00000400, 0x01010400, 0x01010404, 0x00000400, 0x01000404, 0x01010004, 0x01000000, 0x00000004,
\r
51 0x00000404, 0x01000400, 0x01000400, 0x00010400, 0x00010400, 0x01010000, 0x01010000, 0x01000404, 0x00010004,
\r
52 0x01000004, 0x01000004, 0x00010004, 0x00000000, 0x00000404, 0x00010404, 0x01000000, 0x00010000, 0x01010404,
\r
53 0x00000004, 0x01010000, 0x01010400, 0x01000000, 0x01000000, 0x00000400, 0x01010004, 0x00010000, 0x00010400,
\r
54 0x01000004, 0x00000400, 0x00000004, 0x01000404, 0x00010404, 0x01010404, 0x00010004, 0x01010000, 0x01000404,
\r
55 0x01000004, 0x00000404, 0x00010404, 0x01010400, 0x00000404, 0x01000400, 0x01000400, 0x00000000, 0x00010004,
\r
56 0x00010400, 0x00000000, 0x01010004 ];
\r
58 private static const SP2:Array = [ 0x80108020, 0x80008000, 0x00008000, 0x00108020, 0x00100000, 0x00000020, 0x80100020,
\r
59 0x80008020, 0x80000020, 0x80108020, 0x80108000, 0x80000000, 0x80008000, 0x00100000, 0x00000020, 0x80100020,
\r
60 0x00108000, 0x00100020, 0x80008020, 0x00000000, 0x80000000, 0x00008000, 0x00108020, 0x80100000, 0x00100020,
\r
61 0x80000020, 0x00000000, 0x00108000, 0x00008020, 0x80108000, 0x80100000, 0x00008020, 0x00000000, 0x00108020,
\r
62 0x80100020, 0x00100000, 0x80008020, 0x80100000, 0x80108000, 0x00008000, 0x80100000, 0x80008000, 0x00000020,
\r
63 0x80108020, 0x00108020, 0x00000020, 0x00008000, 0x80000000, 0x00008020, 0x80108000, 0x00100000, 0x80000020,
\r
64 0x00100020, 0x80008020, 0x80000020, 0x00100020, 0x00108000, 0x00000000, 0x80008000, 0x00008020, 0x80000000,
\r
65 0x80100020, 0x80108020, 0x00108000 ];
\r
67 private static const SP3:Array = [ 0x00000208, 0x08020200, 0x00000000, 0x08020008, 0x08000200, 0x00000000, 0x00020208,
\r
68 0x08000200, 0x00020008, 0x08000008, 0x08000008, 0x00020000, 0x08020208, 0x00020008, 0x08020000, 0x00000208,
\r
69 0x08000000, 0x00000008, 0x08020200, 0x00000200, 0x00020200, 0x08020000, 0x08020008, 0x00020208, 0x08000208,
\r
70 0x00020200, 0x00020000, 0x08000208, 0x00000008, 0x08020208, 0x00000200, 0x08000000, 0x08020200, 0x08000000,
\r
71 0x00020008, 0x00000208, 0x00020000, 0x08020200, 0x08000200, 0x00000000, 0x00000200, 0x00020008, 0x08020208,
\r
72 0x08000200, 0x08000008, 0x00000200, 0x00000000, 0x08020008, 0x08000208, 0x00020000, 0x08000000, 0x08020208,
\r
73 0x00000008, 0x00020208, 0x00020200, 0x08000008, 0x08020000, 0x08000208, 0x00000208, 0x08020000, 0x00020208,
\r
74 0x00000008, 0x08020008, 0x00020200 ];
\r
76 private static const SP4:Array = [ 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802080, 0x00800081, 0x00800001,
\r
77 0x00002001, 0x00000000, 0x00802000, 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00800080, 0x00800001,
\r
78 0x00000001, 0x00002000, 0x00800000, 0x00802001, 0x00000080, 0x00800000, 0x00002001, 0x00002080, 0x00800081,
\r
79 0x00000001, 0x00002080, 0x00800080, 0x00002000, 0x00802080, 0x00802081, 0x00000081, 0x00800080, 0x00800001,
\r
80 0x00802000, 0x00802081, 0x00000081, 0x00000000, 0x00000000, 0x00802000, 0x00002080, 0x00800080, 0x00800081,
\r
81 0x00000001, 0x00802001, 0x00002081, 0x00002081, 0x00000080, 0x00802081, 0x00000081, 0x00000001, 0x00002000,
\r
82 0x00800001, 0x00002001, 0x00802080, 0x00800081, 0x00002001, 0x00002080, 0x00800000, 0x00802001, 0x00000080,
\r
83 0x00800000, 0x00002000, 0x00802080 ];
\r
85 private static const SP5:Array = [ 0x00000100, 0x02080100, 0x02080000, 0x42000100, 0x00080000, 0x00000100, 0x40000000,
\r
86 0x02080000, 0x40080100, 0x00080000, 0x02000100, 0x40080100, 0x42000100, 0x42080000, 0x00080100, 0x40000000,
\r
87 0x02000000, 0x40080000, 0x40080000, 0x00000000, 0x40000100, 0x42080100, 0x42080100, 0x02000100, 0x42080000,
\r
88 0x40000100, 0x00000000, 0x42000000, 0x02080100, 0x02000000, 0x42000000, 0x00080100, 0x00080000, 0x42000100,
\r
89 0x00000100, 0x02000000, 0x40000000, 0x02080000, 0x42000100, 0x40080100, 0x02000100, 0x40000000, 0x42080000,
\r
90 0x02080100, 0x40080100, 0x00000100, 0x02000000, 0x42080000, 0x42080100, 0x00080100, 0x42000000, 0x42080100,
\r
91 0x02080000, 0x00000000, 0x40080000, 0x42000000, 0x00080100, 0x02000100, 0x40000100, 0x00080000, 0x00000000,
\r
92 0x40080000, 0x02080100, 0x40000100 ];
\r
94 private static const SP6:Array = [ 0x20000010, 0x20400000, 0x00004000, 0x20404010, 0x20400000, 0x00000010, 0x20404010,
\r
95 0x00400000, 0x20004000, 0x00404010, 0x00400000, 0x20000010, 0x00400010, 0x20004000, 0x20000000, 0x00004010,
\r
96 0x00000000, 0x00400010, 0x20004010, 0x00004000, 0x00404000, 0x20004010, 0x00000010, 0x20400010, 0x20400010,
\r
97 0x00000000, 0x00404010, 0x20404000, 0x00004010, 0x00404000, 0x20404000, 0x20000000, 0x20004000, 0x00000010,
\r
98 0x20400010, 0x00404000, 0x20404010, 0x00400000, 0x00004010, 0x20000010, 0x00400000, 0x20004000, 0x20000000,
\r
99 0x00004010, 0x20000010, 0x20404010, 0x00404000, 0x20400000, 0x00404010, 0x20404000, 0x00000000, 0x20400010,
\r
100 0x00000010, 0x00004000, 0x20400000, 0x00404010, 0x00004000, 0x00400010, 0x20004010, 0x00000000, 0x20404000,
\r
101 0x20000000, 0x00400010, 0x20004010 ];
\r
103 private static const SP7:Array = [ 0x00200000, 0x04200002, 0x04000802, 0x00000000, 0x00000800, 0x04000802, 0x00200802,
\r
104 0x04200800, 0x04200802, 0x00200000, 0x00000000, 0x04000002, 0x00000002, 0x04000000, 0x04200002, 0x00000802,
\r
105 0x04000800, 0x00200802, 0x00200002, 0x04000800, 0x04000002, 0x04200000, 0x04200800, 0x00200002, 0x04200000,
\r
106 0x00000800, 0x00000802, 0x04200802, 0x00200800, 0x00000002, 0x04000000, 0x00200800, 0x04000000, 0x00200800,
\r
107 0x00200000, 0x04000802, 0x04000802, 0x04200002, 0x04200002, 0x00000002, 0x00200002, 0x04000000, 0x04000800,
\r
108 0x00200000, 0x04200800, 0x00000802, 0x00200802, 0x04200800, 0x00000802, 0x04000002, 0x04200802, 0x04200000,
\r
109 0x00200800, 0x00000000, 0x00000002, 0x04200802, 0x00000000, 0x00200802, 0x04200000, 0x00000800, 0x04000002,
\r
110 0x04000800, 0x00000800, 0x00200002 ];
\r
112 private static const SP8:Array = [ 0x10001040, 0x00001000, 0x00040000, 0x10041040, 0x10000000, 0x10001040, 0x00000040,
\r
113 0x10000000, 0x00040040, 0x10040000, 0x10041040, 0x00041000, 0x10041000, 0x00041040, 0x00001000, 0x00000040,
\r
114 0x10040000, 0x10000040, 0x10001000, 0x00001040, 0x00041000, 0x00040040, 0x10040040, 0x10041000, 0x00001040,
\r
115 0x00000000, 0x00000000, 0x10040040, 0x10000040, 0x10001000, 0x00041040, 0x00040000, 0x00041040, 0x00040000,
\r
116 0x10041000, 0x00001000, 0x00000040, 0x10040040, 0x00001000, 0x00041040, 0x10001000, 0x00000040, 0x10000040,
\r
117 0x10040000, 0x10040040, 0x10000000, 0x00040000, 0x10001040, 0x00000000, 0x10041040, 0x00040040, 0x10000040,
\r
118 0x10040000, 0x10001000, 0x10001040, 0x00000000, 0x10041040, 0x00041000, 0x00041000, 0x00001040, 0x00001040,
\r
119 0x00040040, 0x10000000, 0x10041000 ];
\r
122 protected var key:ByteArray;
\r
123 protected var encKey:Array;
\r
124 protected var decKey:Array;
\r
127 public function DESKey(key:ByteArray) {
\r
129 this.encKey = generateWorkingKey(true, key, 0);
\r
130 this.decKey = generateWorkingKey(false, key, 0);
\r
133 public function getBlockSize():uint
\r
138 public function decrypt(block:ByteArray, index:uint=0):void
\r
140 desFunc(decKey, block, index, block, index);
\r
143 public function dispose():void
\r
146 for (i=0;i<encKey.length;i++) { encKey[i]=0; }
\r
147 for (i=0;i<decKey.length;i++) { decKey[i]=0; }
\r
150 for (i=0;i<key.length;i++) { key[i]=0; }
\r
156 public function encrypt(block:ByteArray, index:uint=0):void
\r
158 desFunc(encKey, block, index, block, index);
\r
163 * generate an integer based working key based on our secret key and what we
\r
164 * processing we are planning to do.
\r
166 * Acknowledgements for this routine go to James Gillogly & Phil Karn.
\r
168 protected function generateWorkingKey(encrypting:Boolean, key:ByteArray, off:uint):Array
\r
170 //int[] newKey = new int[32];
\r
171 var newKey:Array = [];
\r
172 //boolean[] pc1m = new boolean[56], pcr = new boolean[56];
\r
173 var pc1m:ByteArray = new ByteArray;
\r
174 var pcr:ByteArray = new ByteArray;
\r
178 for (var j:uint = 0; j < 56; j++)
\r
182 pc1m[j] = ((key[off + (l >>> 3)] & bytebit[l & 07]) != 0);
\r
185 for (var i:uint = 0; i < 16; i++)
\r
200 newKey[m] = newKey[n] = 0;
\r
202 for (j = 0; j < 28; j++)
\r
211 pcr[j] = pc1m[l - 28];
\r
215 for (j = 28; j < 56; j++)
\r
224 pcr[j] = pc1m[l - 28];
\r
228 for (j = 0; j < 24; j++)
\r
232 newKey[m] |= bigbyte[j];
\r
235 if (pcr[pc2[j + 24]])
\r
237 newKey[n] |= bigbyte[j];
\r
243 // store the processed key
\r
245 for (i = 0; i != 32; i += 2)
\r
251 i2 = newKey[i + 1];
\r
253 newKey[i] = ((i1 & 0x00fc0000) << 6) | ((i1 & 0x00000fc0) << 10) | ((i2 & 0x00fc0000) >>> 10)
\r
254 | ((i2 & 0x00000fc0) >>> 6);
\r
256 newKey[i + 1] = ((i1 & 0x0003f000) << 12) | ((i1 & 0x0000003f) << 16) | ((i2 & 0x0003f000) >>> 4)
\r
257 | (i2 & 0x0000003f);
\r
265 protected function desFunc(wKey:Array, inp:ByteArray, inOff:uint, out:ByteArray, outOff:uint):void
\r
271 left = (inp[inOff + 0] & 0xff) << 24;
\r
272 left |= (inp[inOff + 1] & 0xff) << 16;
\r
273 left |= (inp[inOff + 2] & 0xff) << 8;
\r
274 left |= (inp[inOff + 3] & 0xff);
\r
276 right = (inp[inOff + 4] & 0xff) << 24;
\r
277 right |= (inp[inOff + 5] & 0xff) << 16;
\r
278 right |= (inp[inOff + 6] & 0xff) << 8;
\r
279 right |= (inp[inOff + 7] & 0xff);
\r
281 work = ((left >>> 4) ^ right) & 0x0f0f0f0f;
\r
283 left ^= (work << 4);
\r
284 work = ((left >>> 16) ^ right) & 0x0000ffff;
\r
286 left ^= (work << 16);
\r
287 work = ((right >>> 2) ^ left) & 0x33333333;
\r
289 right ^= (work << 2);
\r
290 work = ((right >>> 8) ^ left) & 0x00ff00ff;
\r
292 right ^= (work << 8);
\r
293 right = ((right << 1) | ((right >>> 31) & 1)) & 0xffffffff;
\r
294 work = (left ^ right) & 0xaaaaaaaa;
\r
297 left = ((left << 1) | ((left >>> 31) & 1)) & 0xffffffff;
\r
299 for (var round:uint = 0; round < 8; round++)
\r
303 work = (right << 28) | (right >>> 4);
\r
304 work ^= wKey[round * 4 + 0];
\r
305 fval = SP7[work & 0x3f];
\r
306 fval |= SP5[(work >>> 8) & 0x3f];
\r
307 fval |= SP3[(work >>> 16) & 0x3f];
\r
308 fval |= SP1[(work >>> 24) & 0x3f];
\r
309 work = right ^ wKey[round * 4 + 1];
\r
310 fval |= SP8[work & 0x3f];
\r
311 fval |= SP6[(work >>> 8) & 0x3f];
\r
312 fval |= SP4[(work >>> 16) & 0x3f];
\r
313 fval |= SP2[(work >>> 24) & 0x3f];
\r
315 work = (left << 28) | (left >>> 4);
\r
316 work ^= wKey[round * 4 + 2];
\r
317 fval = SP7[work & 0x3f];
\r
318 fval |= SP5[(work >>> 8) & 0x3f];
\r
319 fval |= SP3[(work >>> 16) & 0x3f];
\r
320 fval |= SP1[(work >>> 24) & 0x3f];
\r
321 work = left ^ wKey[round * 4 + 3];
\r
322 fval |= SP8[work & 0x3f];
\r
323 fval |= SP6[(work >>> 8) & 0x3f];
\r
324 fval |= SP4[(work >>> 16) & 0x3f];
\r
325 fval |= SP2[(work >>> 24) & 0x3f];
\r
329 right = (right << 31) | (right >>> 1);
\r
330 work = (left ^ right) & 0xaaaaaaaa;
\r
333 left = (left << 31) | (left >>> 1);
\r
334 work = ((left >>> 8) ^ right) & 0x00ff00ff;
\r
336 left ^= (work << 8);
\r
337 work = ((left >>> 2) ^ right) & 0x33333333;
\r
339 left ^= (work << 2);
\r
340 work = ((right >>> 16) ^ left) & 0x0000ffff;
\r
342 right ^= (work << 16);
\r
343 work = ((right >>> 4) ^ left) & 0x0f0f0f0f;
\r
345 right ^= (work << 4);
\r
347 out[outOff + 0] = ((right >>> 24) & 0xff);
\r
348 out[outOff + 1] = ((right >>> 16) & 0xff);
\r
349 out[outOff + 2] = ((right >>> 8) & 0xff);
\r
350 out[outOff + 3] = (right & 0xff);
\r
351 out[outOff + 4] = ((left >>> 24) & 0xff);
\r
352 out[outOff + 5] = ((left >>> 16) & 0xff);
\r
353 out[outOff + 6] = ((left >>> 8) & 0xff);
\r
354 out[outOff + 7] = (left & 0xff);
\r
358 public function toString():String {
\r