New test.
[mono.git] / mcs / class / corlib / System.Security.Cryptography / DESCryptoServiceProvider.cs
1 //
2 // System.Security.Cryptography.DESCryptoServiceProvider
3 //
4 // Authors:
5 //      Sergey Chaban (serge@wildwestsoftware.com)
6 //      Sebastien Pouliot (sebastien@ximian.com)
7 //
8 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 #if !MOONLIGHT
32
33 using System.Runtime.InteropServices;
34 using Mono.Security.Cryptography;
35
36 namespace System.Security.Cryptography {
37
38         // References:
39         // a.   FIPS PUB 46-3: Data Encryption Standard
40         //      http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
41         
42         internal class DESTransform : SymmetricTransform {
43         
44                 internal static readonly int KEY_BIT_SIZE = 64;
45                 internal static readonly int KEY_BYTE_SIZE = KEY_BIT_SIZE / 8;
46                 internal static readonly int BLOCK_BIT_SIZE = 64;
47                 internal static readonly int BLOCK_BYTE_SIZE = BLOCK_BIT_SIZE / 8;
48         
49                 private byte[] keySchedule;
50                 private byte[] byteBuff;
51                 private uint[] dwordBuff;
52 /*      
53                 // S-boxes from FIPS 46-3, Appendix 1, page 17
54                 private static readonly byte [] sBoxes = {
55                         14,  4, 13,  1,  2, 15, 11,  8,  3, 10,  6, 12,  5,  9,  0,  7,
56                         0, 15,  7,  4, 14,  2, 13,  1, 10,  6, 12, 11,  9,  5,  3,  8,
57                         4,  1, 14,  8, 13,  6,  2, 11, 15, 12,  9,  7,  3, 10,  5,  0,
58                         15, 12,  8,  2,  4,  9,  1,  7,  5, 11,  3, 14, 10,  0,  6, 13,
59         
60                         15,  1,  8, 14,  6, 11,  3,  4,  9,  7,  2, 13, 12,  0,  5, 10,
61                         3, 13,  4,  7, 15,  2,  8, 14, 12,  0,  1, 10,  6,  9, 11,  5,
62                         0, 14,  7, 11, 10,  4, 13,  1,  5,  8, 12,  6,  9,  3,  2, 15,
63                         13,  8, 10,  1,  3, 15,  4,  2, 11,  6,  7, 12,  0,  5, 14,  9,
64         
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                         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                         2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
76                         14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
77                         4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
78                         11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
79         
80                         12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
81                         10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
82                         9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
83                         4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
84         
85                         4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
86                         13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
87                         1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
88                         6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
89         
90                         13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
91                         1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
92                         7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
93                         2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
94                 };
95         
96                 // P table from page 15, also in Appendix 1, page 18
97                 private static readonly byte [] pTab = {        
98                         16-1,  7-1, 20-1, 21-1,
99                         29-1, 12-1, 28-1, 17-1,
100                         1-1, 15-1, 23-1, 26-1,
101                         5-1, 18-1, 31-1, 10-1,
102                         2-1,  8-1, 24-1, 14-1,
103                         32-1, 27-1,  3-1,  9-1,
104                         19-1, 13-1, 30-1,  6-1,
105                         22-1, 11-1,  4-1, 25-1
106                 };
107 */      
108                 // pre-computed result of sBoxes (using pTab)
109                 private static readonly uint[] spBoxes = { 
110                         0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, 
111                         0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, 
112                         0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, 
113                         0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, 
114                         0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, 
115                         0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, 
116                         0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, 
117                         0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, 
118                         0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, 
119                         0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, 
120                         0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, 
121                         0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, 
122                         0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, 
123                         0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, 
124                         0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, 
125                         0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, 
126                         0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, 
127                         0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, 
128                         0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, 
129                         0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, 
130                         0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, 
131                         0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, 
132                         0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, 
133                         0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, 
134                         0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, 
135                         0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, 
136                         0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, 
137                         0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, 
138                         0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, 
139                         0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, 
140                         0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, 
141                         0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, 
142                         0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, 
143                         0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, 
144                         0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, 
145                         0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, 
146                         0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, 
147                         0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, 
148                         0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, 
149                         0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, 
150                         0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, 
151                         0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, 
152                         0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, 
153                         0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, 
154                         0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, 
155                         0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, 
156                         0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, 
157                         0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, 
158                         0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, 
159                         0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, 
160                         0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, 
161                         0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, 
162                         0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, 
163                         0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, 
164                         0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, 
165                         0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, 
166                         0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, 
167                         0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, 
168                         0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, 
169                         0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, 
170                         0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, 
171                         0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, 
172                         0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, 
173                         0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800
174                 };
175         
176                 // Permuted choice 1 table, PC-1, page 19
177                 // Translated to zero-based format.
178                 private static readonly byte [] PC1 = {
179                         57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,
180                         1-1, 58-1, 50-1, 42-1, 34-1, 26-1, 18-1,
181                         10-1,  2-1, 59-1, 51-1, 43-1, 35-1, 27-1,
182                         19-1, 11-1,  3-1, 60-1, 52-1, 44-1, 36-1,
183         
184                         63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,
185                         7-1, 62-1, 54-1, 46-1, 38-1, 30-1, 22-1,
186                         14-1,  6-1, 61-1, 53-1, 45-1, 37-1, 29-1,
187                         21-1, 13-1,  5-1, 28-1, 20-1, 12-1,  4-1
188                 };
189         
190 /*
191                 private static readonly byte [] leftRot = {
192                         1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
193                 };
194 */
195                 // pre-computed result of leftRot
196                 private static readonly byte[] leftRotTotal = { 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1C };
197         
198                 // Permuted choice 2 table, PC-2, page 21
199                 // Translated to zero-based format.
200                 private static readonly byte [] PC2 = {
201                         14-1, 17-1, 11-1, 24-1,  1-1,  5-1,
202                         3-1, 28-1, 15-1,  6-1, 21-1, 10-1,
203                         23-1, 19-1, 12-1,  4-1, 26-1,  8-1,
204                         16-1,  7-1, 27-1, 20-1, 13-1,  2-1,
205                         41-1, 52-1, 31-1, 37-1, 47-1, 55-1,
206                         30-1, 40-1, 51-1, 45-1, 33-1, 48-1,
207                         44-1, 49-1, 39-1, 56-1, 34-1, 53-1,
208                         46-1, 42-1, 50-1, 36-1, 29-1, 32-1
209                 };
210         
211 /*      
212                 // Initial permutation IP, page 10.
213                 // Transposed to 0-based format.
214                 private static readonly byte [] ipBits = {
215                         58-1, 50-1, 42-1, 34-1, 26-1, 18-1, 10-1,  2-1,
216                         60-1, 52-1, 44-1, 36-1, 28-1, 20-1, 12-1,  4-1,
217                         62-1, 54-1, 46-1, 38-1, 30-1, 22-1, 14-1,  6-1,
218                         64-1, 56-1, 48-1, 40-1, 32-1, 24-1, 16-1,  8-1,
219                         57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,  1-1,
220                         59-1, 51-1, 43-1, 35-1, 27-1, 19-1, 11-1,  3-1,
221                         61-1, 53-1, 45-1, 37-1, 29-1, 21-1, 13-1,  5-1,
222                         63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,  7-1
223                 };
224         
225         
226                 // Final permutation FP = IP^(-1), page 10.
227                 // Transposed to 0-based format.
228                 private static readonly byte [] fpBits = {
229                         40-1,  8-1, 48-1, 16-1, 56-1, 24-1, 64-1, 32-1,
230                         39-1,  7-1, 47-1, 15-1, 55-1, 23-1, 63-1, 31-1,
231                         38-1,  6-1, 46-1, 14-1, 54-1, 22-1, 62-1, 30-1,
232                         37-1,  5-1, 45-1, 13-1, 53-1, 21-1, 61-1, 29-1,
233                         36-1,  4-1, 44-1, 12-1, 52-1, 20-1, 60-1, 28-1,
234                         35-1,  3-1, 43-1, 11-1, 51-1, 19-1, 59-1, 27-1,
235                         34-1,  2-1, 42-1, 10-1, 50-1, 18-1, 58-1, 26-1,
236                         33-1,  1-1, 41-1,  9-1, 49-1, 17-1, 57-1, 25-1
237                 };
238 */      
239                 internal static readonly uint[] ipTab = {
240                         0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000, 0x00000100, 0x00000100, 0x00000100, 
241                         0x00000001, 0x00000000, 0x00000101, 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00000100, 
242                         0x00000000, 0x00000001, 0x00000100, 0x00000001, 0x00000000, 0x00000101, 0x00000100, 0x00000101, 
243                         0x00000001, 0x00000001, 0x00000101, 0x00000001, 0x00000001, 0x00000101, 0x00000101, 0x00000101, 
244                         0x00000000, 0x00000000, 0x01000000, 0x00000000, 0x00000000, 0x01000000, 0x01000000, 0x01000000, 
245                         0x00010000, 0x00000000, 0x01010000, 0x00000000, 0x00010000, 0x01000000, 0x01010000, 0x01000000, 
246                         0x00000000, 0x00010000, 0x01000000, 0x00010000, 0x00000000, 0x01010000, 0x01000000, 0x01010000, 
247                         0x00010000, 0x00010000, 0x01010000, 0x00010000, 0x00010000, 0x01010000, 0x01010000, 0x01010000, 
248                         0x00000000, 0x00000000, 0x00000200, 0x00000000, 0x00000000, 0x00000200, 0x00000200, 0x00000200, 
249                         0x00000002, 0x00000000, 0x00000202, 0x00000000, 0x00000002, 0x00000200, 0x00000202, 0x00000200, 
250                         0x00000000, 0x00000002, 0x00000200, 0x00000002, 0x00000000, 0x00000202, 0x00000200, 0x00000202, 
251                         0x00000002, 0x00000002, 0x00000202, 0x00000002, 0x00000002, 0x00000202, 0x00000202, 0x00000202, 
252                         0x00000000, 0x00000000, 0x02000000, 0x00000000, 0x00000000, 0x02000000, 0x02000000, 0x02000000, 
253                         0x00020000, 0x00000000, 0x02020000, 0x00000000, 0x00020000, 0x02000000, 0x02020000, 0x02000000, 
254                         0x00000000, 0x00020000, 0x02000000, 0x00020000, 0x00000000, 0x02020000, 0x02000000, 0x02020000, 
255                         0x00020000, 0x00020000, 0x02020000, 0x00020000, 0x00020000, 0x02020000, 0x02020000, 0x02020000, 
256                         0x00000000, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x00000400, 
257                         0x00000004, 0x00000000, 0x00000404, 0x00000000, 0x00000004, 0x00000400, 0x00000404, 0x00000400, 
258                         0x00000000, 0x00000004, 0x00000400, 0x00000004, 0x00000000, 0x00000404, 0x00000400, 0x00000404, 
259                         0x00000004, 0x00000004, 0x00000404, 0x00000004, 0x00000004, 0x00000404, 0x00000404, 0x00000404, 
260                         0x00000000, 0x00000000, 0x04000000, 0x00000000, 0x00000000, 0x04000000, 0x04000000, 0x04000000, 
261                         0x00040000, 0x00000000, 0x04040000, 0x00000000, 0x00040000, 0x04000000, 0x04040000, 0x04000000, 
262                         0x00000000, 0x00040000, 0x04000000, 0x00040000, 0x00000000, 0x04040000, 0x04000000, 0x04040000, 
263                         0x00040000, 0x00040000, 0x04040000, 0x00040000, 0x00040000, 0x04040000, 0x04040000, 0x04040000, 
264                         0x00000000, 0x00000000, 0x00000800, 0x00000000, 0x00000000, 0x00000800, 0x00000800, 0x00000800, 
265                         0x00000008, 0x00000000, 0x00000808, 0x00000000, 0x00000008, 0x00000800, 0x00000808, 0x00000800, 
266                         0x00000000, 0x00000008, 0x00000800, 0x00000008, 0x00000000, 0x00000808, 0x00000800, 0x00000808, 
267                         0x00000008, 0x00000008, 0x00000808, 0x00000008, 0x00000008, 0x00000808, 0x00000808, 0x00000808, 
268                         0x00000000, 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x08000000, 0x08000000, 0x08000000, 
269                         0x00080000, 0x00000000, 0x08080000, 0x00000000, 0x00080000, 0x08000000, 0x08080000, 0x08000000, 
270                         0x00000000, 0x00080000, 0x08000000, 0x00080000, 0x00000000, 0x08080000, 0x08000000, 0x08080000, 
271                         0x00080000, 0x00080000, 0x08080000, 0x00080000, 0x00080000, 0x08080000, 0x08080000, 0x08080000, 
272                         0x00000000, 0x00000000, 0x00001000, 0x00000000, 0x00000000, 0x00001000, 0x00001000, 0x00001000, 
273                         0x00000010, 0x00000000, 0x00001010, 0x00000000, 0x00000010, 0x00001000, 0x00001010, 0x00001000, 
274                         0x00000000, 0x00000010, 0x00001000, 0x00000010, 0x00000000, 0x00001010, 0x00001000, 0x00001010, 
275                         0x00000010, 0x00000010, 0x00001010, 0x00000010, 0x00000010, 0x00001010, 0x00001010, 0x00001010, 
276                         0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x10000000, 0x10000000, 0x10000000, 
277                         0x00100000, 0x00000000, 0x10100000, 0x00000000, 0x00100000, 0x10000000, 0x10100000, 0x10000000, 
278                         0x00000000, 0x00100000, 0x10000000, 0x00100000, 0x00000000, 0x10100000, 0x10000000, 0x10100000, 
279                         0x00100000, 0x00100000, 0x10100000, 0x00100000, 0x00100000, 0x10100000, 0x10100000, 0x10100000, 
280                         0x00000000, 0x00000000, 0x00002000, 0x00000000, 0x00000000, 0x00002000, 0x00002000, 0x00002000, 
281                         0x00000020, 0x00000000, 0x00002020, 0x00000000, 0x00000020, 0x00002000, 0x00002020, 0x00002000, 
282                         0x00000000, 0x00000020, 0x00002000, 0x00000020, 0x00000000, 0x00002020, 0x00002000, 0x00002020, 
283                         0x00000020, 0x00000020, 0x00002020, 0x00000020, 0x00000020, 0x00002020, 0x00002020, 0x00002020, 
284                         0x00000000, 0x00000000, 0x20000000, 0x00000000, 0x00000000, 0x20000000, 0x20000000, 0x20000000, 
285                         0x00200000, 0x00000000, 0x20200000, 0x00000000, 0x00200000, 0x20000000, 0x20200000, 0x20000000, 
286                         0x00000000, 0x00200000, 0x20000000, 0x00200000, 0x00000000, 0x20200000, 0x20000000, 0x20200000, 
287                         0x00200000, 0x00200000, 0x20200000, 0x00200000, 0x00200000, 0x20200000, 0x20200000, 0x20200000, 
288                         0x00000000, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 
289                         0x00000040, 0x00000000, 0x00004040, 0x00000000, 0x00000040, 0x00004000, 0x00004040, 0x00004000, 
290                         0x00000000, 0x00000040, 0x00004000, 0x00000040, 0x00000000, 0x00004040, 0x00004000, 0x00004040, 
291                         0x00000040, 0x00000040, 0x00004040, 0x00000040, 0x00000040, 0x00004040, 0x00004040, 0x00004040, 
292                         0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000, 0x40000000, 0x40000000, 0x40000000, 
293                         0x00400000, 0x00000000, 0x40400000, 0x00000000, 0x00400000, 0x40000000, 0x40400000, 0x40000000, 
294                         0x00000000, 0x00400000, 0x40000000, 0x00400000, 0x00000000, 0x40400000, 0x40000000, 0x40400000, 
295                         0x00400000, 0x00400000, 0x40400000, 0x00400000, 0x00400000, 0x40400000, 0x40400000, 0x40400000, 
296                         0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00008000, 0x00008000, 0x00008000, 
297                         0x00000080, 0x00000000, 0x00008080, 0x00000000, 0x00000080, 0x00008000, 0x00008080, 0x00008000, 
298                         0x00000000, 0x00000080, 0x00008000, 0x00000080, 0x00000000, 0x00008080, 0x00008000, 0x00008080, 
299                         0x00000080, 0x00000080, 0x00008080, 0x00000080, 0x00000080, 0x00008080, 0x00008080, 0x00008080, 
300                         0x00000000, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000, 
301                         0x00800000, 0x00000000, 0x80800000, 0x00000000, 0x00800000, 0x80000000, 0x80800000, 0x80000000, 
302                         0x00000000, 0x00800000, 0x80000000, 0x00800000, 0x00000000, 0x80800000, 0x80000000, 0x80800000, 
303                         0x00800000, 0x00800000, 0x80800000, 0x00800000, 0x00800000, 0x80800000, 0x80800000, 0x80800000 
304                 };
305
306                 internal static readonly uint[] fpTab = { 
307                         0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00004000, 0x00000000, 0x00004040, 
308                         0x00000000, 0x00400000, 0x00000000, 0x00400040, 0x00000000, 0x00404000, 0x00000000, 0x00404040, 
309                         0x00000000, 0x40000000, 0x00000000, 0x40000040, 0x00000000, 0x40004000, 0x00000000, 0x40004040, 
310                         0x00000000, 0x40400000, 0x00000000, 0x40400040, 0x00000000, 0x40404000, 0x00000000, 0x40404040, 
311                         0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00004000, 0x00000000, 0x00004040, 0x00000000, 
312                         0x00400000, 0x00000000, 0x00400040, 0x00000000, 0x00404000, 0x00000000, 0x00404040, 0x00000000, 
313                         0x40000000, 0x00000000, 0x40000040, 0x00000000, 0x40004000, 0x00000000, 0x40004040, 0x00000000, 
314                         0x40400000, 0x00000000, 0x40400040, 0x00000000, 0x40404000, 0x00000000, 0x40404040, 0x00000000, 
315                         0x00000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000, 0x00001000, 0x00000000, 0x00001010, 
316                         0x00000000, 0x00100000, 0x00000000, 0x00100010, 0x00000000, 0x00101000, 0x00000000, 0x00101010, 
317                         0x00000000, 0x10000000, 0x00000000, 0x10000010, 0x00000000, 0x10001000, 0x00000000, 0x10001010, 
318                         0x00000000, 0x10100000, 0x00000000, 0x10100010, 0x00000000, 0x10101000, 0x00000000, 0x10101010, 
319                         0x00000000, 0x00000000, 0x00000010, 0x00000000, 0x00001000, 0x00000000, 0x00001010, 0x00000000, 
320                         0x00100000, 0x00000000, 0x00100010, 0x00000000, 0x00101000, 0x00000000, 0x00101010, 0x00000000, 
321                         0x10000000, 0x00000000, 0x10000010, 0x00000000, 0x10001000, 0x00000000, 0x10001010, 0x00000000, 
322                         0x10100000, 0x00000000, 0x10100010, 0x00000000, 0x10101000, 0x00000000, 0x10101010, 0x00000000, 
323                         0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x00000400, 0x00000000, 0x00000404, 
324                         0x00000000, 0x00040000, 0x00000000, 0x00040004, 0x00000000, 0x00040400, 0x00000000, 0x00040404, 
325                         0x00000000, 0x04000000, 0x00000000, 0x04000004, 0x00000000, 0x04000400, 0x00000000, 0x04000404, 
326                         0x00000000, 0x04040000, 0x00000000, 0x04040004, 0x00000000, 0x04040400, 0x00000000, 0x04040404, 
327                         0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x00000400, 0x00000000, 0x00000404, 0x00000000, 
328                         0x00040000, 0x00000000, 0x00040004, 0x00000000, 0x00040400, 0x00000000, 0x00040404, 0x00000000, 
329                         0x04000000, 0x00000000, 0x04000004, 0x00000000, 0x04000400, 0x00000000, 0x04000404, 0x00000000, 
330                         0x04040000, 0x00000000, 0x04040004, 0x00000000, 0x04040400, 0x00000000, 0x04040404, 0x00000000, 
331                         0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000100, 0x00000000, 0x00000101, 
332                         0x00000000, 0x00010000, 0x00000000, 0x00010001, 0x00000000, 0x00010100, 0x00000000, 0x00010101, 
333                         0x00000000, 0x01000000, 0x00000000, 0x01000001, 0x00000000, 0x01000100, 0x00000000, 0x01000101, 
334                         0x00000000, 0x01010000, 0x00000000, 0x01010001, 0x00000000, 0x01010100, 0x00000000, 0x01010101, 
335                         0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000100, 0x00000000, 0x00000101, 0x00000000, 
336                         0x00010000, 0x00000000, 0x00010001, 0x00000000, 0x00010100, 0x00000000, 0x00010101, 0x00000000, 
337                         0x01000000, 0x00000000, 0x01000001, 0x00000000, 0x01000100, 0x00000000, 0x01000101, 0x00000000, 
338                         0x01010000, 0x00000000, 0x01010001, 0x00000000, 0x01010100, 0x00000000, 0x01010101, 0x00000000, 
339                         0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x00000000, 0x00008000, 0x00000000, 0x00008080, 
340                         0x00000000, 0x00800000, 0x00000000, 0x00800080, 0x00000000, 0x00808000, 0x00000000, 0x00808080, 
341                         0x00000000, 0x80000000, 0x00000000, 0x80000080, 0x00000000, 0x80008000, 0x00000000, 0x80008080, 
342                         0x00000000, 0x80800000, 0x00000000, 0x80800080, 0x00000000, 0x80808000, 0x00000000, 0x80808080, 
343                         0x00000000, 0x00000000, 0x00000080, 0x00000000, 0x00008000, 0x00000000, 0x00008080, 0x00000000, 
344                         0x00800000, 0x00000000, 0x00800080, 0x00000000, 0x00808000, 0x00000000, 0x00808080, 0x00000000, 
345                         0x80000000, 0x00000000, 0x80000080, 0x00000000, 0x80008000, 0x00000000, 0x80008080, 0x00000000, 
346                         0x80800000, 0x00000000, 0x80800080, 0x00000000, 0x80808000, 0x00000000, 0x80808080, 0x00000000, 
347                         0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00002000, 0x00000000, 0x00002020, 
348                         0x00000000, 0x00200000, 0x00000000, 0x00200020, 0x00000000, 0x00202000, 0x00000000, 0x00202020, 
349                         0x00000000, 0x20000000, 0x00000000, 0x20000020, 0x00000000, 0x20002000, 0x00000000, 0x20002020, 
350                         0x00000000, 0x20200000, 0x00000000, 0x20200020, 0x00000000, 0x20202000, 0x00000000, 0x20202020, 
351                         0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00002000, 0x00000000, 0x00002020, 0x00000000, 
352                         0x00200000, 0x00000000, 0x00200020, 0x00000000, 0x00202000, 0x00000000, 0x00202020, 0x00000000, 
353                         0x20000000, 0x00000000, 0x20000020, 0x00000000, 0x20002000, 0x00000000, 0x20002020, 0x00000000, 
354                         0x20200000, 0x00000000, 0x20200020, 0x00000000, 0x20202000, 0x00000000, 0x20202020, 0x00000000, 
355                         0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x00000000, 0x00000800, 0x00000000, 0x00000808, 
356                         0x00000000, 0x00080000, 0x00000000, 0x00080008, 0x00000000, 0x00080800, 0x00000000, 0x00080808, 
357                         0x00000000, 0x08000000, 0x00000000, 0x08000008, 0x00000000, 0x08000800, 0x00000000, 0x08000808, 
358                         0x00000000, 0x08080000, 0x00000000, 0x08080008, 0x00000000, 0x08080800, 0x00000000, 0x08080808, 
359                         0x00000000, 0x00000000, 0x00000008, 0x00000000, 0x00000800, 0x00000000, 0x00000808, 0x00000000, 
360                         0x00080000, 0x00000000, 0x00080008, 0x00000000, 0x00080800, 0x00000000, 0x00080808, 0x00000000, 
361                         0x08000000, 0x00000000, 0x08000008, 0x00000000, 0x08000800, 0x00000000, 0x08000808, 0x00000000, 
362                         0x08080000, 0x00000000, 0x08080008, 0x00000000, 0x08080800, 0x00000000, 0x08080808, 0x00000000, 
363                         0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000200, 0x00000000, 0x00000202, 
364                         0x00000000, 0x00020000, 0x00000000, 0x00020002, 0x00000000, 0x00020200, 0x00000000, 0x00020202, 
365                         0x00000000, 0x02000000, 0x00000000, 0x02000002, 0x00000000, 0x02000200, 0x00000000, 0x02000202, 
366                         0x00000000, 0x02020000, 0x00000000, 0x02020002, 0x00000000, 0x02020200, 0x00000000, 0x02020202, 
367                         0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000200, 0x00000000, 0x00000202, 0x00000000, 
368                         0x00020000, 0x00000000, 0x00020002, 0x00000000, 0x00020200, 0x00000000, 0x00020202, 0x00000000, 
369                         0x02000000, 0x00000000, 0x02000002, 0x00000000, 0x02000200, 0x00000000, 0x02000202, 0x00000000, 
370                         0x02020000, 0x00000000, 0x02020002, 0x00000000, 0x02020200, 0x00000000, 0x02020202, 0x00000000 
371                         };
372
373 /*              static DESTransform ()
374                 {
375                         spBoxes = new uint [64 * 8];
376         
377                         int [] pBox = new int [32];
378         
379                         for (int p = 0; p < 32; p++) {
380                                 for (int i = 0; i < 32; i++) {
381                                         if (p == pTab [i]) {
382                                                 pBox [p] = i;
383                                                 break;
384                                         }
385                                 }
386                         }
387         
388                         for (int s = 0; s < 8; s++) { // for each S-box
389                                 int sOff = s << 6;
390         
391                                 for (int i = 0; i < 64; i++) { // inputs
392                                         uint sp=0;
393         
394                                         int indx = (i & 0x20) | ((i & 1) << 4) | ((i >> 1) & 0xF);
395         
396                                         for (int j = 0; j < 4; j++) { // for each bit in the output
397                                                 if ((sBoxes [sOff + indx] & (8 >> j)) != 0) {
398                                                         sp |= (uint) (1 << (31 - pBox [(s << 2) + j]));
399                                                 }
400                                         }
401         
402                                         spBoxes [sOff + i] = sp;
403                                 }
404                         }
405
406                         leftRotTotal = new byte [leftRot.Length];
407         
408                         for (int i = 0; i < leftRot.Length; i++) {
409                                 int r = 0;
410                                 for (int j = 0; j <= i; r += leftRot [j++]) {
411                                         // no statement (confuse the compiler == warning)
412                                 }
413                                 leftRotTotal [i]  = (byte) r;
414                         }
415
416                         InitPermutationTable (ipBits, out ipTab);
417                         InitPermutationTable (fpBits, out fpTab);
418                 }
419 */      
420                 // Default constructor.
421                 internal DESTransform (SymmetricAlgorithm symmAlgo, bool encryption, byte[] key, byte[] iv) 
422                         : base (symmAlgo, encryption, iv)
423                 {
424                         byte[] clonedKey = null;
425                         if (key == null) {
426                                 key = GetStrongKey ();
427                                 clonedKey = key; // no need to clone
428                         }
429                         // note: checking (semi-)weak keys also checks valid key length
430                         if (DES.IsWeakKey (key) || DES.IsSemiWeakKey (key)) {
431                                 string msg = Locale.GetText ("This is a known weak, or semi-weak, key.");
432                                 throw new CryptographicException (msg);
433                         }
434
435                         if (clonedKey == null)
436                                 clonedKey = (byte[]) key.Clone ();
437
438                         keySchedule = new byte [KEY_BYTE_SIZE * 16];
439                         byteBuff = new byte [BLOCK_BYTE_SIZE];
440                         dwordBuff = new uint [BLOCK_BYTE_SIZE / 4];
441                         SetKey (clonedKey);
442                 }
443
444 /* Permutation Tables are now precomputed.
445                 private static void InitPermutationTable (byte[] pBits, out int[] permTab)
446                 {
447                         permTab = new int [8*2 * 8*2 * (64/32)];
448         
449                         for (int i = 0; i < 16; i++) {
450                                 for (int j = 0; j < 16; j++) {
451                                         int offs = (i << 5) + (j << 1);
452                                         for (int n = 0; n < 64; n++) {
453                                                 int bitNum = (int) pBits [n];
454                                                 if ((bitNum >> 2 == i) &&
455                                                         0 != (j & (8 >> (bitNum & 3)))) {
456                                                         permTab [offs + (n >> (3+2))] |= (int) ((0x80808080 & (0xFF << (n & (3 << 3)))) >> (n & 7));
457                                                 }
458                                         }
459                                 }
460                         }
461                 }
462 */
463
464                 private uint CipherFunct (uint r, int n)
465                 {
466                         uint res = 0;
467                         byte[] subkey = keySchedule;
468                         int i = n << 3;
469         
470                         uint rt = (r >> 1) | (r << 31); // ROR32(r)
471                         res |= spBoxes [0*64 + (((rt >> 26) ^ subkey [i++]) & 0x3F)];
472                         res |= spBoxes [1*64 + (((rt >> 22) ^ subkey [i++]) & 0x3F)];
473                         res |= spBoxes [2*64 + (((rt >> 18) ^ subkey [i++]) & 0x3F)];
474                         res |= spBoxes [3*64 + (((rt >> 14) ^ subkey [i++]) & 0x3F)];
475                         res |= spBoxes [4*64 + (((rt >> 10) ^ subkey [i++]) & 0x3F)];
476                         res |= spBoxes [5*64 + (((rt >>  6) ^ subkey [i++]) & 0x3F)];
477                         res |= spBoxes [6*64 + (((rt >>  2) ^ subkey [i++]) & 0x3F)];
478                         rt = (r << 1) | (r >> 31); // ROL32(r)
479                         res |= spBoxes [7*64 + ((rt ^ subkey [i]) & 0x3F)];
480                         return res;
481                 }
482         
483                 internal static void Permutation (byte[] input, byte[] output, uint[] permTab, bool preSwap)
484                 {
485                         if (preSwap && BitConverter.IsLittleEndian)
486                                 BSwap (input);
487         
488                         int offs1 = (((int)(input [0]) >> 4)) << 1;
489                         int offs2 = (1 << 5) + ((((int)input [0]) & 0xF) << 1);
490         
491                         uint d1 = permTab [offs1++] | permTab [offs2++];
492                         uint d2 = permTab [offs1]   | permTab [offs2];
493         
494                         int max = BLOCK_BYTE_SIZE << 1;
495                         for (int i = 2, indx = 1; i < max; i += 2, indx++) {
496                                 int ii = (int) input [indx];
497                                 offs1 = (i << 5) + ((ii >> 4) << 1);
498                                 offs2 = ((i + 1) << 5) + ((ii & 0xF) << 1);
499         
500                                 d1 |= permTab [offs1++] | permTab [offs2++];
501                                 d2 |= permTab [offs1]   | permTab [offs2];
502                         }
503         
504                         if (preSwap || !BitConverter.IsLittleEndian) {
505                                 output [0] = (byte) (d1);
506                                 output [1] = (byte) (d1 >> 8);
507                                 output [2] = (byte) (d1 >> 16);
508                                 output [3] = (byte) (d1 >> 24);
509                                 output [4] = (byte) (d2);
510                                 output [5] = (byte) (d2 >> 8);
511                                 output [6] = (byte) (d2 >> 16);
512                                 output [7] = (byte) (d2 >> 24);
513                         }
514                         else {
515                                 output [0] = (byte) (d1 >> 24);
516                                 output [1] = (byte) (d1 >> 16);
517                                 output [2] = (byte) (d1 >> 8);
518                                 output [3] = (byte) (d1);
519                                 output [4] = (byte) (d2 >> 24);
520                                 output [5] = (byte) (d2 >> 16);
521                                 output [6] = (byte) (d2 >> 8);
522                                 output [7] = (byte) (d2);
523                         }
524                 }
525         
526                 private static void BSwap (byte [] byteBuff)
527                 {
528                         byte t = byteBuff [0];
529                         byteBuff [0] = byteBuff [3];
530                         byteBuff [3] = t;
531         
532                         t = byteBuff [1];
533                         byteBuff [1] = byteBuff [2];
534                         byteBuff [2] = t;
535         
536                         t = byteBuff [4];
537                         byteBuff [4] = byteBuff [7];
538                         byteBuff [7] = t;
539         
540                         t = byteBuff [5];
541                         byteBuff [5] = byteBuff [6];
542                         byteBuff [6] = t;
543                 }
544         
545                 internal void SetKey (byte[] key)
546                 {
547                         // NOTE: see Fig. 3, Key schedule calculation, at page 20.
548                         Array.Clear (keySchedule, 0, keySchedule.Length);
549         
550                         int keyBitSize = PC1.Length;
551         
552                         byte[] keyPC1 = new byte [keyBitSize]; // PC1-permuted key
553                         byte[] keyRot = new byte [keyBitSize]; // PC1 & rotated
554         
555                         int indx = 0;
556         
557                         foreach (byte bitPos in PC1) {
558                                 keyPC1 [indx++] = (byte)((key [(int)bitPos >> 3] >> (7 ^ (bitPos & 7))) & 1);
559                         }
560         
561                         int j;
562                         for (int i = 0; i < KEY_BYTE_SIZE*2; i++) {
563                                 int b = keyBitSize >> 1;
564         
565                                 for (j = 0; j < b; j++) {
566                                         int s = j + (int) leftRotTotal [i];
567                                         keyRot [j] = keyPC1 [s < b ? s : s - b];
568                                 }
569         
570                                 for (j = b; j < keyBitSize; j++) {
571                                         int s = j + (int) leftRotTotal [i];
572                                         keyRot [j] = keyPC1 [s < keyBitSize ? s : s - b];
573                                 }
574         
575                                 int keyOffs = i * KEY_BYTE_SIZE;
576         
577                                 j = 0;
578                                 foreach (byte bitPos in PC2) {
579                                         if (keyRot [(int)bitPos] != 0) {
580                                                 keySchedule [keyOffs + (j/6)] |= (byte) (0x80 >> ((j % 6) + 2));
581                                         }
582                                         j++;
583                                 }
584                         }
585                 }
586         
587                 // public helper for TripleDES
588                 public void ProcessBlock (byte[] input, byte[] output) 
589                 {
590                         Buffer.BlockCopy (input, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
591         
592                         if (encrypt) {
593                                 uint d0 = dwordBuff [0];
594                                 uint d1 = dwordBuff [1];
595         
596                                 // 16 rounds
597                                 d0 ^= CipherFunct (d1,  0);
598                                 d1 ^= CipherFunct (d0,  1);
599                                 d0 ^= CipherFunct (d1,  2);
600                                 d1 ^= CipherFunct (d0,  3);
601                                 d0 ^= CipherFunct (d1,  4);
602                                 d1 ^= CipherFunct (d0,  5);
603                                 d0 ^= CipherFunct (d1,  6);
604                                 d1 ^= CipherFunct (d0,  7);
605                                 d0 ^= CipherFunct (d1,  8);
606                                 d1 ^= CipherFunct (d0,  9);
607                                 d0 ^= CipherFunct (d1, 10);
608                                 d1 ^= CipherFunct (d0, 11);
609                                 d0 ^= CipherFunct (d1, 12);
610                                 d1 ^= CipherFunct (d0, 13);
611                                 d0 ^= CipherFunct (d1, 14);
612                                 d1 ^= CipherFunct (d0, 15);
613         
614                                 dwordBuff [0] = d1;
615                                 dwordBuff [1] = d0;
616                         }
617                         else {
618                                 uint d1 = dwordBuff [0];
619                                 uint d0 = dwordBuff [1];
620         
621                                 // 16 rounds in reverse order
622                                 d1 ^= CipherFunct (d0, 15);
623                                 d0 ^= CipherFunct (d1, 14);
624                                 d1 ^= CipherFunct (d0, 13);
625                                 d0 ^= CipherFunct (d1, 12);
626                                 d1 ^= CipherFunct (d0, 11);
627                                 d0 ^= CipherFunct (d1, 10);
628                                 d1 ^= CipherFunct (d0,  9);
629                                 d0 ^= CipherFunct (d1,  8);
630                                 d1 ^= CipherFunct (d0,  7);
631                                 d0 ^= CipherFunct (d1,  6);
632                                 d1 ^= CipherFunct (d0,  5);
633                                 d0 ^= CipherFunct (d1,  4);
634                                 d1 ^= CipherFunct (d0,  3);
635                                 d0 ^= CipherFunct (d1,  2);
636                                 d1 ^= CipherFunct (d0,  1);
637                                 d0 ^= CipherFunct (d1,  0);
638         
639                                 dwordBuff [0] = d0;
640                                 dwordBuff [1] = d1;
641                         }
642         
643                         Buffer.BlockCopy (dwordBuff, 0, output, 0, BLOCK_BYTE_SIZE);
644                 }
645         
646                 protected override void ECB (byte[] input, byte[] output) 
647                 {
648                         Permutation (input, output, ipTab, false);
649                         ProcessBlock (output, byteBuff);
650                         Permutation (byteBuff, output, fpTab, true);
651                 }
652
653                 static internal byte[] GetStrongKey ()
654                 {
655                         byte[] key = KeyBuilder.Key (DESTransform.KEY_BYTE_SIZE);
656                         while (DES.IsWeakKey (key) || DES.IsSemiWeakKey (key))
657                                 key = KeyBuilder.Key (DESTransform.KEY_BYTE_SIZE);
658                         return key;
659                 }
660         } 
661         
662         [ComVisible (true)]
663         public sealed class DESCryptoServiceProvider : DES {
664         
665                 public DESCryptoServiceProvider ()
666                 {
667                 }
668         
669                 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
670                 {
671                         return new DESTransform (this, false, rgbKey, rgbIV);
672                 }
673         
674                 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
675                 {
676                         return new DESTransform (this, true, rgbKey, rgbIV);
677                 }
678         
679                 public override void GenerateIV () 
680                 {
681                         IVValue = KeyBuilder.IV (DESTransform.BLOCK_BYTE_SIZE);
682                 }
683         
684                 public override void GenerateKey () 
685                 {
686                         KeyValue = DESTransform.GetStrongKey ();
687                 }
688         }
689 }
690
691 #endif
692