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