Base64Table now supports both encoding and decoding tables.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / DES.cs
1 //
2 // System.Security.Cryptography.DES
3 //
4 // Author:
5 //   Sergey Chaban (serge@wildwestsoftware.com)
6 //
7
8 using System;
9 using System.Security.Cryptography;
10
11 // References: FIPS PUB 46-3
12
13 namespace System.Security.Cryptography {
14
15
16         internal sealed class DESCore {
17
18                 internal static readonly int KEY_BIT_SIZE = 64;
19                 internal static readonly int KEY_BYTE_SIZE = KEY_BIT_SIZE / 8;
20                 internal static readonly int BLOCK_BIT_SIZE = 64;
21                 internal static readonly int BLOCK_BYTE_SIZE = BLOCK_BIT_SIZE / 8;
22
23                 private byte [] keySchedule;
24                 private byte [] byteBuff;
25                 private uint [] dwordBuff;
26
27                 internal delegate void DESCall (byte [] block, byte [] output);
28
29
30                 // Ek(Ek(m)) = m
31                 internal static ulong [] weakKeys = {
32                         0x0101010101010101, /* 0000000 0000000 */
33                         0xFEFEFEFEFEFEFEFE, /* FFFFFFF FFFFFFF */
34                         0x1F1F1F1FE0E0E0E0, /* 0000000 FFFFFFF */
35                         0xE0E0E0E01F1F1F1F  /* FFFFFFF 0000000 */
36                 };
37
38                 // Ek1(Ek2(m)) = m
39                 internal static ulong [] semiweakKeys = {
40                         0x01FE01FE01FE01FE, 0xFE01FE01FE01FE01,
41                         0x1FE01FE00EF10EF1, 0xE01FE01FF10EF10E,
42                         0x01E001E001F101F1, 0xE001E001F101F101,
43                         0x1FFE1FFE0EFE0EFE, 0xFE1FFE1FFE0EFE0E,
44                         0x011F011F010E010E, 0x1F011F010E010E01,
45                         0xE0FEE0FEF1FEF1FE, 0xFEE0FEE0FEF1FEF1
46                 };
47
48
49
50                 // S-boxes from FIPS 46-3, Appendix 1, page 17
51                 private static byte [] sBoxes = {
52                                                 /* S1 */
53                         14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
54                          0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
55                          4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
56                         15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
57
58                                                 /* S2 */
59                         15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
60                          3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
61                          0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
62                         13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
63
64                                                 /* S3 */
65                         10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
66                         13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
67                         13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
68                          1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
69
70                                                 /* S4 */
71                          7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
72                         13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
73                         10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
74                          3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
75
76                                                 /* S5 */
77                          2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
78                         14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
79                          4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
80                         11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
81
82                                                 /* S6 */
83                         12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
84                         10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
85                          9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
86                          4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
87
88                                                 /* S7 */
89                          4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
90                         13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
91                          1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
92                          6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
93
94                                                 /* S8 */
95                         13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
96                          1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
97                          7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
98                          2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
99                 };
100
101
102                 // P table from page 15, also in Appendix 1, page 18
103                 private static byte [] pTab = { 
104                         16-1,  7-1, 20-1, 21-1,
105                         29-1, 12-1, 28-1, 17-1,
106                          1-1, 15-1, 23-1, 26-1,
107                          5-1, 18-1, 31-1, 10-1,
108                          2-1,  8-1, 24-1, 14-1,
109                         32-1, 27-1,  3-1,  9-1,
110                         19-1, 13-1, 30-1,  6-1,
111                         22-1, 11-1,  4-1, 25-1
112                 };
113
114
115                 // Permuted choice 1 table, PC-1, page 19
116                 // Translated to zero-based format.
117                 private static byte [] PC1 = {
118                         57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,
119                          1-1, 58-1, 50-1, 42-1, 34-1, 26-1, 18-1,
120                         10-1,  2-1, 59-1, 51-1, 43-1, 35-1, 27-1,
121                         19-1, 11-1,  3-1, 60-1, 52-1, 44-1, 36-1,
122
123                         63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,
124                          7-1, 62-1, 54-1, 46-1, 38-1, 30-1, 22-1,
125                         14-1,  6-1, 61-1, 53-1, 45-1, 37-1, 29-1,
126                         21-1, 13-1,  5-1, 28-1, 20-1, 12-1,  4-1
127                 };
128
129
130                 private static byte [] leftRot = {
131                         1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
132                 };
133
134                 private static byte [] leftRotTotal;
135
136
137
138                 // Permuted choice 2 table, PC-2, page 21
139                 // Translated to zero-based format.
140                 private static byte [] PC2 = {
141                         14-1, 17-1, 11-1, 24-1,  1-1,  5-1,
142                          3-1, 28-1, 15-1,  6-1, 21-1, 10-1,
143                         23-1, 19-1, 12-1,  4-1, 26-1,  8-1,
144                         16-1,  7-1, 27-1, 20-1, 13-1,  2-1,
145                         41-1, 52-1, 31-1, 37-1, 47-1, 55-1,
146                         30-1, 40-1, 51-1, 45-1, 33-1, 48-1,
147                         44-1, 49-1, 39-1, 56-1, 34-1, 53-1,
148                         46-1, 42-1, 50-1, 36-1, 29-1, 32-1
149                 };
150
151
152                 // Initial permutation IP, page 10.
153                 // Transposed to 0-based format.
154                 private static byte [] ipBits = {
155                         58-1, 50-1, 42-1, 34-1, 26-1, 18-1, 10-1,  2-1,
156                         60-1, 52-1, 44-1, 36-1, 28-1, 20-1, 12-1,  4-1,
157                         62-1, 54-1, 46-1, 38-1, 30-1, 22-1, 14-1,  6-1,
158                         64-1, 56-1, 48-1, 40-1, 32-1, 24-1, 16-1,  8-1,
159                         57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,  1-1,
160                         59-1, 51-1, 43-1, 35-1, 27-1, 19-1, 11-1,  3-1,
161                         61-1, 53-1, 45-1, 37-1, 29-1, 21-1, 13-1,  5-1,
162                         63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,  7-1
163                 };
164
165
166                 // Final permutation FP = IP^(-1), page 10.
167                 // Transposed to 0-based format.
168                 private static byte [] fpBits = {
169                         40-1,  8-1, 48-1, 16-1, 56-1, 24-1, 64-1, 32-1,
170                         39-1,  7-1, 47-1, 15-1, 55-1, 23-1, 63-1, 31-1,
171                         38-1,  6-1, 46-1, 14-1, 54-1, 22-1, 62-1, 30-1,
172                         37-1,  5-1, 45-1, 13-1, 53-1, 21-1, 61-1, 29-1,
173                         36-1,  4-1, 44-1, 12-1, 52-1, 20-1, 60-1, 28-1,
174                         35-1,  3-1, 43-1, 11-1, 51-1, 19-1, 59-1, 27-1,
175                         34-1,  2-1, 42-1, 10-1, 50-1, 18-1, 58-1, 26-1,
176                         33-1,  1-1, 41-1,  9-1, 49-1, 17-1, 57-1, 25-1
177                 };
178
179
180
181                 private static uint [] spBoxes;
182                 private static byte [] ipTab;
183                 private static byte [] fpTab;
184
185
186                 static DESCore ()
187                 {
188                         spBoxes = new uint [64 * 8];
189
190                         int [] pBox = new int [32];
191
192                         for (int p = 0; p < 32; p++) {
193                                 for (int i = 0; i < 32; i++) {
194                                         if (p == pTab [i]) {
195                                                 pBox [p] = i;
196                                                 break;
197                                         }
198                                 }
199                         }
200
201
202                         for (int s = 0; s < 8; s++) { // for each S-box
203                                 int sOff = s << 6;
204
205                                 for (int i = 0; i < 64; i++) { // inputs
206                                         uint sp=0;
207
208                                         int indx = (i & 0x20) | ((i & 1) << 4) | ((i >> 1) & 0xF);
209
210                                         for (int j = 0; j < 4; j++) { // for each bit in the output
211                                                 if ((sBoxes [sOff + indx] & (8 >> j)) != 0) {
212                                                         sp |= (uint) (1 << (31 - pBox [(s << 2) + j]));
213                                                 }
214                                         }
215
216                                         spBoxes [sOff + i] = sp;
217                                 }
218                         }
219
220
221                         leftRotTotal = new byte [leftRot.Length];
222
223
224                         for (int i = 0; i < leftRot.Length; i++) {
225                                 int r = 0;
226                                 for (int j = 0; j <= i; r += leftRot [j++]);
227                                 leftRotTotal [i]  = (byte) r;
228                         }
229
230
231                         InitPermutationTable (ipBits, out ipTab);
232                         InitPermutationTable (fpBits, out fpTab);
233
234                 } // class constructor
235
236
237
238                 // Default constructor.
239                 internal DESCore ()
240                 {
241                         keySchedule = new byte [KEY_BYTE_SIZE * 16];
242                         byteBuff = new byte [BLOCK_BYTE_SIZE];
243                         dwordBuff = new uint [BLOCK_BYTE_SIZE / 4];
244                 }
245
246
247
248
249                 private static void InitPermutationTable (byte [] pBits, out byte [] permTab)
250                 {
251                         permTab = new byte [8*2 * 8*2 * (64/8)];
252
253                         for (int i = 0; i < 16; i++) {
254                                 for (int j = 0; j < 16; j++) {
255                                         int offs = (i << 7) + (j << 3);
256                                         for (int n = 0; n < 64; n++) {
257                                                 int bitNum = (int) pBits [n];
258                                                 if ((bitNum >> 2 == i) &&
259                                                     0 != (j & (8 >> (bitNum & 3)))) {
260                                                         permTab [offs + (n >> 3)] |= (byte) (0x80 >> (n & 7));
261                                                 }
262                                         }
263                                 }
264                         }
265                 }
266
267
268
269                 internal static ulong PackKey (byte [] key)
270                 {
271                         ulong res = 0;
272                         for (int i = 0, sh = 8*KEY_BYTE_SIZE; (sh = sh - 8) >= 0; i++) {
273                                 res |= (ulong) key [i] << sh;
274                         }
275                         return res;
276                 }
277
278
279
280                 internal static byte [] UnpackKey (ulong key)
281                 {
282                         byte [] res = new byte [KEY_BYTE_SIZE];
283                         for (int i = 0, sh = 8*KEY_BYTE_SIZE; (sh = sh - 8) >= 0; i++) {
284                                 res [i] = (byte) (key >> sh);
285                         }
286                         return res;
287                 }
288
289
290
291                 internal static bool IsValidKeySize (byte [] key)
292                 {
293                         return (key.Length == KEY_BYTE_SIZE);
294                 }
295
296
297
298                 private uint CipherFunct(uint r, int n)
299                 {
300                         uint res = 0;
301                         byte [] subkey = keySchedule;
302                         int i = n << 3;
303
304                         uint rt = (r >> 1) | (r << 31); // ROR32(r)
305                         res |= spBoxes [0*64 + (((rt >> 26) ^ subkey [i++]) & 0x3F)];
306                         res |= spBoxes [1*64 + (((rt >> 22) ^ subkey [i++]) & 0x3F)];
307                         res |= spBoxes [2*64 + (((rt >> 18) ^ subkey [i++]) & 0x3F)];
308                         res |= spBoxes [3*64 + (((rt >> 14) ^ subkey [i++]) & 0x3F)];
309                         res |= spBoxes [4*64 + (((rt >> 10) ^ subkey [i++]) & 0x3F)];
310                         res |= spBoxes [5*64 + (((rt >>  6) ^ subkey [i++]) & 0x3F)];
311                         res |= spBoxes [6*64 + (((rt >>  2) ^ subkey [i++]) & 0x3F)];
312                         rt = (r << 1) | (r >> 31); // ROL32(r)
313                         res |= spBoxes [7*64 + ((rt ^ subkey [i]) & 0x3F)];
314
315                         return res;
316                 }
317
318
319                 /*
320                 private static void Permutation (byte [] input, byte [] output, byte [] permTab)
321                 {
322                         Array.Clear (output, 0, BLOCK_BYTE_SIZE);
323
324                         for (int i = 0, indx = 0; i < BLOCK_BYTE_SIZE*2; i += 2, indx++) {
325                                 int offs1 = (i << 7) + ((((int)(input [indx]) >> 4)) << 3);
326                                 int offs2 = ((i + 1) << 7) + ((((int)input [indx]) & 0xF) << 3);
327
328                                 for (int j = 0; j < 8; j++) {
329                                         output [j] |= (byte) (permTab [offs1++] | permTab [offs2++]);
330                                 }
331                         }
332                 }
333                 */
334
335                 private static void Permutation (byte [] input, byte [] _output, byte [] permTab)
336                 {
337                         byte [] output = _output;
338                         Array.Clear (output, 0, BLOCK_BYTE_SIZE);
339
340                         int offs1 = (((int)(input [0]) >> 4)) << 3;
341                         int offs2 = (1 << 7) + ((((int)input [0]) & 0xF) << 3);
342
343                         output [0] |= (byte) (permTab [offs1++] | permTab [offs2++]);
344                         output [1] |= (byte) (permTab [offs1++] | permTab [offs2++]);
345                         output [2] |= (byte) (permTab [offs1++] | permTab [offs2++]);
346                         output [3] |= (byte) (permTab [offs1++] | permTab [offs2++]);
347                         output [4] |= (byte) (permTab [offs1++] | permTab [offs2++]);
348                         output [5] |= (byte) (permTab [offs1++] | permTab [offs2++]);
349                         output [6] |= (byte) (permTab [offs1++] | permTab [offs2++]);
350                         output [7] |= (byte) (permTab [offs1]   | permTab [offs2]);
351
352                         for (int i = 2, indx = 1; i < BLOCK_BYTE_SIZE*2; i += 2, indx++) {
353                                 offs1 = (i << 7) + ((((int)(input [indx]) >> 4)) << 3);
354                                 offs2 = ((i + 1) << 7) + ((((int)input [indx]) & 0xF) << 3);
355
356                                 output [0] |= (byte) (permTab [offs1++] | permTab [offs2++]);
357                                 output [1] |= (byte) (permTab [offs1++] | permTab [offs2++]);
358                                 output [2] |= (byte) (permTab [offs1++] | permTab [offs2++]);
359                                 output [3] |= (byte) (permTab [offs1++] | permTab [offs2++]);
360                                 output [4] |= (byte) (permTab [offs1++] | permTab [offs2++]);
361                                 output [5] |= (byte) (permTab [offs1++] | permTab [offs2++]);
362                                 output [6] |= (byte) (permTab [offs1++] | permTab [offs2++]);
363                                 output [7] |= (byte) (permTab [offs1]   | permTab [offs2]);
364                         }
365                 }
366
367
368
369
370                 private void BSwap ()
371                 {
372                         byte t;
373
374                         // byte [] byteBuff = this.byteBuff;
375
376                         t = byteBuff [0];
377                         byteBuff [0] = byteBuff [3];
378                         byteBuff [3] = t;
379
380                         t = byteBuff [1];
381                         byteBuff [1] = byteBuff [2];
382                         byteBuff [2] = t;
383
384                         t = byteBuff [4];
385                         byteBuff [4] = byteBuff [7];
386                         byteBuff [7] = t;
387
388                         t = byteBuff [5];
389                         byteBuff [5] = byteBuff [6];
390                         byteBuff [6] = t;
391                 }
392
393
394
395                 internal void SetKey (byte [] key)
396                 {
397                         // NOTE: see Fig. 3, Key schedule calculation, at page 20.
398
399                         Array.Clear (keySchedule, 0, keySchedule.Length);
400
401                         int keyBitSize = PC1.Length;
402
403                         byte [] keyPC1 = new byte [keyBitSize]; // PC1-permuted key
404                         byte [] keyRot = new byte [keyBitSize]; // PC1 & rotated
405
406                         int indx = 0;
407
408                         foreach (byte bitPos in PC1) {
409                                 keyPC1 [indx++] = (byte)((key [(int)bitPos >> 3] >> (7 ^ (bitPos & 7))) & 1);
410                         }
411
412
413
414
415                         int j;
416                         for (int i = 0; i < KEY_BYTE_SIZE*2; i++) {
417                                 int b = keyBitSize >> 1;
418
419                                 for (j = 0; j < b; j++) {
420                                         int s = j + (int) leftRotTotal [i];
421                                         keyRot [j] = keyPC1 [s < b ? s : s - b];
422                                 }
423
424                                 for (j = b; j < keyBitSize; j++) {
425                                         int s = j + (int) leftRotTotal [i];
426                                         keyRot [j] = keyPC1 [s < keyBitSize ? s : s - b];
427                                 }
428
429                                 int keyOffs = i * KEY_BYTE_SIZE;
430
431                                 j = 0;
432                                 foreach (byte bitPos in PC2) {
433                                         if (keyRot [(int)bitPos] != 0) {
434                                                 keySchedule [keyOffs + (j/6)] |= (byte) (0x80 >> ((j % 6) + 2));
435                                         }
436                                         j++;
437                                 }
438                         }
439
440                 }
441
442
443
444                 internal void Encrypt (byte [] block, byte [] output)
445                 {
446                         byte [] dest = (output == null ? block : output);
447
448                         byte [] byteBuff = this.byteBuff;
449                         uint [] dwordBuff = this.dwordBuff;
450
451                         Permutation (block, byteBuff, ipTab);
452
453
454                         BSwap ();
455                         Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
456
457                         // 16 rounds
458                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  0);
459                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  1);
460                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  2);
461                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  3);
462                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  4);
463                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  5);
464                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  6);
465                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  7);
466                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  8);
467                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  9);
468                         dwordBuff[0] ^= CipherFunct (dwordBuff [1], 10);
469                         dwordBuff[1] ^= CipherFunct (dwordBuff [0], 11);
470                         dwordBuff[0] ^= CipherFunct (dwordBuff [1], 12);
471                         dwordBuff[1] ^= CipherFunct (dwordBuff [0], 13);
472                         dwordBuff[0] ^= CipherFunct (dwordBuff [1], 14);
473                         dwordBuff[1] ^= CipherFunct (dwordBuff [0], 15);
474
475
476                         uint t = dwordBuff [0];
477                         dwordBuff [0] = dwordBuff [1];
478                         dwordBuff [1] = t;
479                         Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
480                         BSwap();
481
482                         Permutation (byteBuff, dest, fpTab);
483                 }
484
485
486                 internal void Decrypt (byte [] block, byte [] output)
487                 {
488                         byte [] dest = (output == null ? block : output);
489
490                         byte [] byteBuff = this.byteBuff;
491                         uint [] dwordBuff = this.dwordBuff;
492
493                         Permutation (block, byteBuff, ipTab);
494
495                         BSwap ();
496                         Buffer.BlockCopy (byteBuff, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
497
498                         uint t = dwordBuff [0];
499                         dwordBuff [0] = dwordBuff [1];
500                         dwordBuff [1] = t;
501
502                         // 16 rounds in reverse order
503                         dwordBuff[1] ^= CipherFunct (dwordBuff [0], 15);
504                         dwordBuff[0] ^= CipherFunct (dwordBuff [1], 14);
505                         dwordBuff[1] ^= CipherFunct (dwordBuff [0], 13);
506                         dwordBuff[0] ^= CipherFunct (dwordBuff [1], 12);
507                         dwordBuff[1] ^= CipherFunct (dwordBuff [0], 11);
508                         dwordBuff[0] ^= CipherFunct (dwordBuff [1], 10);
509                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  9);
510                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  8);
511                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  7);
512                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  6);
513                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  5);
514                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  4);
515                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  3);
516                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  2);
517                         dwordBuff[1] ^= CipherFunct (dwordBuff [0],  1);
518                         dwordBuff[0] ^= CipherFunct (dwordBuff [1],  0);
519
520
521
522                         Buffer.BlockCopy (dwordBuff, 0, byteBuff, 0, BLOCK_BYTE_SIZE);
523                         BSwap();
524
525                         Permutation (byteBuff, dest, fpTab);
526                 }
527
528
529         } // DESCore
530
531
532
533
534         public abstract class DES : SymmetricAlgorithm {
535                 private byte [] key;
536
537                 public DES ()
538                 {
539                 }
540
541                 public static new DES Create()
542                 {
543                         // TODO: implement
544                         return null;
545                 }
546
547                 public static new DES Create(string name)
548                 {
549                         // TODO: implement
550                         return null;
551                 }
552
553
554                 public static bool IsWeakKey (byte [] rgbKey)
555                 {
556                         if (!DESCore.IsValidKeySize (rgbKey)) {
557                                 throw new CryptographicException ();
558                         }
559
560                         ulong lk = DESCore.PackKey (rgbKey);
561                         foreach (ulong wk in DESCore.weakKeys) {
562                                 if (lk == wk) return true;
563                         }
564                         return false;
565                 }
566
567
568                 public static bool IsSemiWeakKey (byte [] rgbKey)
569                 {
570                         if (!DESCore.IsValidKeySize (rgbKey)) {
571                                 throw new CryptographicException ();
572                         }
573
574                         ulong lk = DESCore.PackKey (rgbKey);
575                         foreach (ulong swk in DESCore.semiweakKeys) {
576                                 if (lk == swk) return true;
577                         }
578                         return false;
579                 }
580
581                 public override byte[] Key {
582                         get {
583                                 return this.key;
584                         }
585                         set {
586                                 this.key = new byte [DESCore.KEY_BYTE_SIZE];
587                                 Array.Copy (value, 0, this.key, 0, DESCore.KEY_BYTE_SIZE);
588                         }
589                 }
590
591         } // DES
592
593 } // System.Security.Cryptography