Make a copy of the old ZipLib
[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 using System.Runtime.InteropServices;
32 using Mono.Security.Cryptography;
33
34 namespace System.Security.Cryptography {
35
36         // References:
37         // a.   FIPS PUB 46-3: Data Encryption Standard
38         //      http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
39         
40         internal class DESTransform : SymmetricTransform {
41         
42                 internal static readonly int KEY_BIT_SIZE = 64;
43                 internal static readonly int KEY_BYTE_SIZE = KEY_BIT_SIZE / 8;
44                 internal static readonly int BLOCK_BIT_SIZE = 64;
45                 internal static readonly int BLOCK_BYTE_SIZE = BLOCK_BIT_SIZE / 8;
46         
47                 private byte[] keySchedule;
48                 private byte[] byteBuff;
49                 private uint[] dwordBuff;
50 /*      
51                 // S-boxes from FIPS 46-3, Appendix 1, page 17
52                 private static readonly byte [] sBoxes = {
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                         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                         10,  0,  9, 14,  6,  3, 15,  5,  1, 13, 12,  7, 11,  4,  2,  8,
64                         13,  7,  0,  9,  3,  4,  6, 10,  2,  8,  5, 14, 12, 11, 15,  1,
65                         13,  6,  4,  9,  8, 15,  3,  0, 11,  1,  2, 12,  5, 10, 14,  7,
66                         1, 10, 13,  0,  6,  9,  8,  7,  4, 15, 14,  3, 11,  5,  2, 12,
67         
68                         7, 13, 14,  3,  0,  6,  9, 10,  1,  2,  8,  5, 11, 12,  4, 15,
69                         13,  8, 11,  5,  6, 15,  0,  3,  4,  7,  2, 12,  1, 10, 14,  9,
70                         10,  6,  9,  0, 12, 11,  7, 13, 15,  1,  3, 14,  5,  2,  8,  4,
71                         3, 15,  0,  6, 10,  1, 13,  8,  9,  4,  5, 11, 12,  7,  2, 14,
72         
73                         2, 12,  4,  1,  7, 10, 11,  6,  8,  5,  3, 15, 13,  0, 14,  9,
74                         14, 11,  2, 12,  4,  7, 13,  1,  5,  0, 15, 10,  3,  9,  8,  6,
75                         4,  2,  1, 11, 10, 13,  7,  8, 15,  9, 12,  5,  6,  3,  0, 14,
76                         11,  8, 12,  7,  1, 14,  2, 13,  6, 15,  0,  9, 10,  4,  5,  3,
77         
78                         12,  1, 10, 15,  9,  2,  6,  8,  0, 13,  3,  4, 14,  7,  5, 11,
79                         10, 15,  4,  2,  7, 12,  9,  5,  6,  1, 13, 14,  0, 11,  3,  8,
80                         9, 14, 15,  5,  2,  8, 12,  3,  7,  0,  4, 10,  1, 13, 11,  6,
81                         4,  3,  2, 12,  9,  5, 15, 10, 11, 14,  1,  7,  6,  0,  8, 13,
82         
83                         4, 11,  2, 14, 15,  0,  8, 13,  3, 12,  9,  7,  5, 10,  6,  1,
84                         13,  0, 11,  7,  4,  9,  1, 10, 14,  3,  5, 12,  2, 15,  8,  6,
85                         1,  4, 11, 13, 12,  3,  7, 14, 10, 15,  6,  8,  0,  5,  9,  2,
86                         6, 11, 13,  8,  1,  4, 10,  7,  9,  5,  0, 15, 14,  2,  3, 12,
87         
88                         13,  2,  8,  4,  6, 15, 11,  1, 10,  9,  3, 14,  5,  0, 12,  7,
89                         1, 15, 13,  8, 10,  3,  7,  4, 12,  5,  6, 11,  0, 14,  9,  2,
90                         7, 11,  4,  1,  9, 12, 14,  2,  0,  6, 10, 13, 15,  3,  5,  8,
91                         2,  1, 14,  7,  4, 10,  8, 13, 15, 12,  9,  0,  3,  5,  6, 11
92                 };
93         
94                 // P table from page 15, also in Appendix 1, page 18
95                 private static readonly byte [] pTab = {        
96                         16-1,  7-1, 20-1, 21-1,
97                         29-1, 12-1, 28-1, 17-1,
98                         1-1, 15-1, 23-1, 26-1,
99                         5-1, 18-1, 31-1, 10-1,
100                         2-1,  8-1, 24-1, 14-1,
101                         32-1, 27-1,  3-1,  9-1,
102                         19-1, 13-1, 30-1,  6-1,
103                         22-1, 11-1,  4-1, 25-1
104                 };
105 */      
106                 // pre-computed result of sBoxes (using pTab)
107                 private static readonly uint[] spBoxes = { 
108                         0x00808200, 0x00000000, 0x00008000, 0x00808202, 0x00808002, 0x00008202, 0x00000002, 0x00008000, 
109                         0x00000200, 0x00808200, 0x00808202, 0x00000200, 0x00800202, 0x00808002, 0x00800000, 0x00000002, 
110                         0x00000202, 0x00800200, 0x00800200, 0x00008200, 0x00008200, 0x00808000, 0x00808000, 0x00800202, 
111                         0x00008002, 0x00800002, 0x00800002, 0x00008002, 0x00000000, 0x00000202, 0x00008202, 0x00800000, 
112                         0x00008000, 0x00808202, 0x00000002, 0x00808000, 0x00808200, 0x00800000, 0x00800000, 0x00000200, 
113                         0x00808002, 0x00008000, 0x00008200, 0x00800002, 0x00000200, 0x00000002, 0x00800202, 0x00008202, 
114                         0x00808202, 0x00008002, 0x00808000, 0x00800202, 0x00800002, 0x00000202, 0x00008202, 0x00808200, 
115                         0x00000202, 0x00800200, 0x00800200, 0x00000000, 0x00008002, 0x00008200, 0x00000000, 0x00808002, 
116                         0x40084010, 0x40004000, 0x00004000, 0x00084010, 0x00080000, 0x00000010, 0x40080010, 0x40004010, 
117                         0x40000010, 0x40084010, 0x40084000, 0x40000000, 0x40004000, 0x00080000, 0x00000010, 0x40080010, 
118                         0x00084000, 0x00080010, 0x40004010, 0x00000000, 0x40000000, 0x00004000, 0x00084010, 0x40080000, 
119                         0x00080010, 0x40000010, 0x00000000, 0x00084000, 0x00004010, 0x40084000, 0x40080000, 0x00004010, 
120                         0x00000000, 0x00084010, 0x40080010, 0x00080000, 0x40004010, 0x40080000, 0x40084000, 0x00004000, 
121                         0x40080000, 0x40004000, 0x00000010, 0x40084010, 0x00084010, 0x00000010, 0x00004000, 0x40000000, 
122                         0x00004010, 0x40084000, 0x00080000, 0x40000010, 0x00080010, 0x40004010, 0x40000010, 0x00080010, 
123                         0x00084000, 0x00000000, 0x40004000, 0x00004010, 0x40000000, 0x40080010, 0x40084010, 0x00084000, 
124                         0x00000104, 0x04010100, 0x00000000, 0x04010004, 0x04000100, 0x00000000, 0x00010104, 0x04000100, 
125                         0x00010004, 0x04000004, 0x04000004, 0x00010000, 0x04010104, 0x00010004, 0x04010000, 0x00000104, 
126                         0x04000000, 0x00000004, 0x04010100, 0x00000100, 0x00010100, 0x04010000, 0x04010004, 0x00010104, 
127                         0x04000104, 0x00010100, 0x00010000, 0x04000104, 0x00000004, 0x04010104, 0x00000100, 0x04000000, 
128                         0x04010100, 0x04000000, 0x00010004, 0x00000104, 0x00010000, 0x04010100, 0x04000100, 0x00000000, 
129                         0x00000100, 0x00010004, 0x04010104, 0x04000100, 0x04000004, 0x00000100, 0x00000000, 0x04010004, 
130                         0x04000104, 0x00010000, 0x04000000, 0x04010104, 0x00000004, 0x00010104, 0x00010100, 0x04000004, 
131                         0x04010000, 0x04000104, 0x00000104, 0x04010000, 0x00010104, 0x00000004, 0x04010004, 0x00010100, 
132                         0x80401000, 0x80001040, 0x80001040, 0x00000040, 0x00401040, 0x80400040, 0x80400000, 0x80001000, 
133                         0x00000000, 0x00401000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00400040, 0x80400000, 
134                         0x80000000, 0x00001000, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x80001000, 0x00001040, 
135                         0x80400040, 0x80000000, 0x00001040, 0x00400040, 0x00001000, 0x00401040, 0x80401040, 0x80000040, 
136                         0x00400040, 0x80400000, 0x00401000, 0x80401040, 0x80000040, 0x00000000, 0x00000000, 0x00401000, 
137                         0x00001040, 0x00400040, 0x80400040, 0x80000000, 0x80401000, 0x80001040, 0x80001040, 0x00000040, 
138                         0x80401040, 0x80000040, 0x80000000, 0x00001000, 0x80400000, 0x80001000, 0x00401040, 0x80400040, 
139                         0x80001000, 0x00001040, 0x00400000, 0x80401000, 0x00000040, 0x00400000, 0x00001000, 0x00401040, 
140                         0x00000080, 0x01040080, 0x01040000, 0x21000080, 0x00040000, 0x00000080, 0x20000000, 0x01040000, 
141                         0x20040080, 0x00040000, 0x01000080, 0x20040080, 0x21000080, 0x21040000, 0x00040080, 0x20000000, 
142                         0x01000000, 0x20040000, 0x20040000, 0x00000000, 0x20000080, 0x21040080, 0x21040080, 0x01000080, 
143                         0x21040000, 0x20000080, 0x00000000, 0x21000000, 0x01040080, 0x01000000, 0x21000000, 0x00040080, 
144                         0x00040000, 0x21000080, 0x00000080, 0x01000000, 0x20000000, 0x01040000, 0x21000080, 0x20040080, 
145                         0x01000080, 0x20000000, 0x21040000, 0x01040080, 0x20040080, 0x00000080, 0x01000000, 0x21040000, 
146                         0x21040080, 0x00040080, 0x21000000, 0x21040080, 0x01040000, 0x00000000, 0x20040000, 0x21000000, 
147                         0x00040080, 0x01000080, 0x20000080, 0x00040000, 0x00000000, 0x20040000, 0x01040080, 0x20000080, 
148                         0x10000008, 0x10200000, 0x00002000, 0x10202008, 0x10200000, 0x00000008, 0x10202008, 0x00200000, 
149                         0x10002000, 0x00202008, 0x00200000, 0x10000008, 0x00200008, 0x10002000, 0x10000000, 0x00002008, 
150                         0x00000000, 0x00200008, 0x10002008, 0x00002000, 0x00202000, 0x10002008, 0x00000008, 0x10200008, 
151                         0x10200008, 0x00000000, 0x00202008, 0x10202000, 0x00002008, 0x00202000, 0x10202000, 0x10000000, 
152                         0x10002000, 0x00000008, 0x10200008, 0x00202000, 0x10202008, 0x00200000, 0x00002008, 0x10000008, 
153                         0x00200000, 0x10002000, 0x10000000, 0x00002008, 0x10000008, 0x10202008, 0x00202000, 0x10200000, 
154                         0x00202008, 0x10202000, 0x00000000, 0x10200008, 0x00000008, 0x00002000, 0x10200000, 0x00202008, 
155                         0x00002000, 0x00200008, 0x10002008, 0x00000000, 0x10202000, 0x10000000, 0x00200008, 0x10002008, 
156                         0x00100000, 0x02100001, 0x02000401, 0x00000000, 0x00000400, 0x02000401, 0x00100401, 0x02100400, 
157                         0x02100401, 0x00100000, 0x00000000, 0x02000001, 0x00000001, 0x02000000, 0x02100001, 0x00000401, 
158                         0x02000400, 0x00100401, 0x00100001, 0x02000400, 0x02000001, 0x02100000, 0x02100400, 0x00100001, 
159                         0x02100000, 0x00000400, 0x00000401, 0x02100401, 0x00100400, 0x00000001, 0x02000000, 0x00100400, 
160                         0x02000000, 0x00100400, 0x00100000, 0x02000401, 0x02000401, 0x02100001, 0x02100001, 0x00000001, 
161                         0x00100001, 0x02000000, 0x02000400, 0x00100000, 0x02100400, 0x00000401, 0x00100401, 0x02100400, 
162                         0x00000401, 0x02000001, 0x02100401, 0x02100000, 0x00100400, 0x00000000, 0x00000001, 0x02100401, 
163                         0x00000000, 0x00100401, 0x02100000, 0x00000400, 0x02000001, 0x02000400, 0x00000400, 0x00100001, 
164                         0x08000820, 0x00000800, 0x00020000, 0x08020820, 0x08000000, 0x08000820, 0x00000020, 0x08000000, 
165                         0x00020020, 0x08020000, 0x08020820, 0x00020800, 0x08020800, 0x00020820, 0x00000800, 0x00000020, 
166                         0x08020000, 0x08000020, 0x08000800, 0x00000820, 0x00020800, 0x00020020, 0x08020020, 0x08020800, 
167                         0x00000820, 0x00000000, 0x00000000, 0x08020020, 0x08000020, 0x08000800, 0x00020820, 0x00020000, 
168                         0x00020820, 0x00020000, 0x08020800, 0x00000800, 0x00000020, 0x08020020, 0x00000800, 0x00020820, 
169                         0x08000800, 0x00000020, 0x08000020, 0x08020000, 0x08020020, 0x08000000, 0x00020000, 0x08000820, 
170                         0x00000000, 0x08020820, 0x00020020, 0x08000020, 0x08020000, 0x08000800, 0x08000820, 0x00000000, 
171                         0x08020820, 0x00020800, 0x00020800, 0x00000820, 0x00000820, 0x00020020, 0x08000000, 0x08020800
172                 };
173         
174                 // Permuted choice 1 table, PC-1, page 19
175                 // Translated to zero-based format.
176                 private static readonly byte [] PC1 = {
177                         57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,
178                         1-1, 58-1, 50-1, 42-1, 34-1, 26-1, 18-1,
179                         10-1,  2-1, 59-1, 51-1, 43-1, 35-1, 27-1,
180                         19-1, 11-1,  3-1, 60-1, 52-1, 44-1, 36-1,
181         
182                         63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,
183                         7-1, 62-1, 54-1, 46-1, 38-1, 30-1, 22-1,
184                         14-1,  6-1, 61-1, 53-1, 45-1, 37-1, 29-1,
185                         21-1, 13-1,  5-1, 28-1, 20-1, 12-1,  4-1
186                 };
187         
188 /*
189                 private static readonly byte [] leftRot = {
190                         1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
191                 };
192 */
193                 // pre-computed result of leftRot
194                 private static readonly byte[] leftRotTotal = { 0x01, 0x02, 0x04, 0x06, 0x08, 0x0A, 0x0C, 0x0E, 0x0F, 0x11, 0x13, 0x15, 0x17, 0x19, 0x1B, 0x1C };
195         
196                 // Permuted choice 2 table, PC-2, page 21
197                 // Translated to zero-based format.
198                 private static readonly byte [] PC2 = {
199                         14-1, 17-1, 11-1, 24-1,  1-1,  5-1,
200                         3-1, 28-1, 15-1,  6-1, 21-1, 10-1,
201                         23-1, 19-1, 12-1,  4-1, 26-1,  8-1,
202                         16-1,  7-1, 27-1, 20-1, 13-1,  2-1,
203                         41-1, 52-1, 31-1, 37-1, 47-1, 55-1,
204                         30-1, 40-1, 51-1, 45-1, 33-1, 48-1,
205                         44-1, 49-1, 39-1, 56-1, 34-1, 53-1,
206                         46-1, 42-1, 50-1, 36-1, 29-1, 32-1
207                 };
208         
209 /*      
210                 // Initial permutation IP, page 10.
211                 // Transposed to 0-based format.
212                 private static readonly byte [] ipBits = {
213                         58-1, 50-1, 42-1, 34-1, 26-1, 18-1, 10-1,  2-1,
214                         60-1, 52-1, 44-1, 36-1, 28-1, 20-1, 12-1,  4-1,
215                         62-1, 54-1, 46-1, 38-1, 30-1, 22-1, 14-1,  6-1,
216                         64-1, 56-1, 48-1, 40-1, 32-1, 24-1, 16-1,  8-1,
217                         57-1, 49-1, 41-1, 33-1, 25-1, 17-1,  9-1,  1-1,
218                         59-1, 51-1, 43-1, 35-1, 27-1, 19-1, 11-1,  3-1,
219                         61-1, 53-1, 45-1, 37-1, 29-1, 21-1, 13-1,  5-1,
220                         63-1, 55-1, 47-1, 39-1, 31-1, 23-1, 15-1,  7-1
221                 };
222         
223         
224                 // Final permutation FP = IP^(-1), page 10.
225                 // Transposed to 0-based format.
226                 private static readonly byte [] fpBits = {
227                         40-1,  8-1, 48-1, 16-1, 56-1, 24-1, 64-1, 32-1,
228                         39-1,  7-1, 47-1, 15-1, 55-1, 23-1, 63-1, 31-1,
229                         38-1,  6-1, 46-1, 14-1, 54-1, 22-1, 62-1, 30-1,
230                         37-1,  5-1, 45-1, 13-1, 53-1, 21-1, 61-1, 29-1,
231                         36-1,  4-1, 44-1, 12-1, 52-1, 20-1, 60-1, 28-1,
232                         35-1,  3-1, 43-1, 11-1, 51-1, 19-1, 59-1, 27-1,
233                         34-1,  2-1, 42-1, 10-1, 50-1, 18-1, 58-1, 26-1,
234                         33-1,  1-1, 41-1,  9-1, 49-1, 17-1, 57-1, 25-1
235                 };
236 */      
237                 internal static readonly uint[] ipTab = {
238                         0x00000000, 0x00000000, 0x00000100, 0x00000000, 0x00000000, 0x00000100, 0x00000100, 0x00000100, 
239                         0x00000001, 0x00000000, 0x00000101, 0x00000000, 0x00000001, 0x00000100, 0x00000101, 0x00000100, 
240                         0x00000000, 0x00000001, 0x00000100, 0x00000001, 0x00000000, 0x00000101, 0x00000100, 0x00000101, 
241                         0x00000001, 0x00000001, 0x00000101, 0x00000001, 0x00000001, 0x00000101, 0x00000101, 0x00000101, 
242                         0x00000000, 0x00000000, 0x01000000, 0x00000000, 0x00000000, 0x01000000, 0x01000000, 0x01000000, 
243                         0x00010000, 0x00000000, 0x01010000, 0x00000000, 0x00010000, 0x01000000, 0x01010000, 0x01000000, 
244                         0x00000000, 0x00010000, 0x01000000, 0x00010000, 0x00000000, 0x01010000, 0x01000000, 0x01010000, 
245                         0x00010000, 0x00010000, 0x01010000, 0x00010000, 0x00010000, 0x01010000, 0x01010000, 0x01010000, 
246                         0x00000000, 0x00000000, 0x00000200, 0x00000000, 0x00000000, 0x00000200, 0x00000200, 0x00000200, 
247                         0x00000002, 0x00000000, 0x00000202, 0x00000000, 0x00000002, 0x00000200, 0x00000202, 0x00000200, 
248                         0x00000000, 0x00000002, 0x00000200, 0x00000002, 0x00000000, 0x00000202, 0x00000200, 0x00000202, 
249                         0x00000002, 0x00000002, 0x00000202, 0x00000002, 0x00000002, 0x00000202, 0x00000202, 0x00000202, 
250                         0x00000000, 0x00000000, 0x02000000, 0x00000000, 0x00000000, 0x02000000, 0x02000000, 0x02000000, 
251                         0x00020000, 0x00000000, 0x02020000, 0x00000000, 0x00020000, 0x02000000, 0x02020000, 0x02000000, 
252                         0x00000000, 0x00020000, 0x02000000, 0x00020000, 0x00000000, 0x02020000, 0x02000000, 0x02020000, 
253                         0x00020000, 0x00020000, 0x02020000, 0x00020000, 0x00020000, 0x02020000, 0x02020000, 0x02020000, 
254                         0x00000000, 0x00000000, 0x00000400, 0x00000000, 0x00000000, 0x00000400, 0x00000400, 0x00000400, 
255                         0x00000004, 0x00000000, 0x00000404, 0x00000000, 0x00000004, 0x00000400, 0x00000404, 0x00000400, 
256                         0x00000000, 0x00000004, 0x00000400, 0x00000004, 0x00000000, 0x00000404, 0x00000400, 0x00000404, 
257                         0x00000004, 0x00000004, 0x00000404, 0x00000004, 0x00000004, 0x00000404, 0x00000404, 0x00000404, 
258                         0x00000000, 0x00000000, 0x04000000, 0x00000000, 0x00000000, 0x04000000, 0x04000000, 0x04000000, 
259                         0x00040000, 0x00000000, 0x04040000, 0x00000000, 0x00040000, 0x04000000, 0x04040000, 0x04000000, 
260                         0x00000000, 0x00040000, 0x04000000, 0x00040000, 0x00000000, 0x04040000, 0x04000000, 0x04040000, 
261                         0x00040000, 0x00040000, 0x04040000, 0x00040000, 0x00040000, 0x04040000, 0x04040000, 0x04040000, 
262                         0x00000000, 0x00000000, 0x00000800, 0x00000000, 0x00000000, 0x00000800, 0x00000800, 0x00000800, 
263                         0x00000008, 0x00000000, 0x00000808, 0x00000000, 0x00000008, 0x00000800, 0x00000808, 0x00000800, 
264                         0x00000000, 0x00000008, 0x00000800, 0x00000008, 0x00000000, 0x00000808, 0x00000800, 0x00000808, 
265                         0x00000008, 0x00000008, 0x00000808, 0x00000008, 0x00000008, 0x00000808, 0x00000808, 0x00000808, 
266                         0x00000000, 0x00000000, 0x08000000, 0x00000000, 0x00000000, 0x08000000, 0x08000000, 0x08000000, 
267                         0x00080000, 0x00000000, 0x08080000, 0x00000000, 0x00080000, 0x08000000, 0x08080000, 0x08000000, 
268                         0x00000000, 0x00080000, 0x08000000, 0x00080000, 0x00000000, 0x08080000, 0x08000000, 0x08080000, 
269                         0x00080000, 0x00080000, 0x08080000, 0x00080000, 0x00080000, 0x08080000, 0x08080000, 0x08080000, 
270                         0x00000000, 0x00000000, 0x00001000, 0x00000000, 0x00000000, 0x00001000, 0x00001000, 0x00001000, 
271                         0x00000010, 0x00000000, 0x00001010, 0x00000000, 0x00000010, 0x00001000, 0x00001010, 0x00001000, 
272                         0x00000000, 0x00000010, 0x00001000, 0x00000010, 0x00000000, 0x00001010, 0x00001000, 0x00001010, 
273                         0x00000010, 0x00000010, 0x00001010, 0x00000010, 0x00000010, 0x00001010, 0x00001010, 0x00001010, 
274                         0x00000000, 0x00000000, 0x10000000, 0x00000000, 0x00000000, 0x10000000, 0x10000000, 0x10000000, 
275                         0x00100000, 0x00000000, 0x10100000, 0x00000000, 0x00100000, 0x10000000, 0x10100000, 0x10000000, 
276                         0x00000000, 0x00100000, 0x10000000, 0x00100000, 0x00000000, 0x10100000, 0x10000000, 0x10100000, 
277                         0x00100000, 0x00100000, 0x10100000, 0x00100000, 0x00100000, 0x10100000, 0x10100000, 0x10100000, 
278                         0x00000000, 0x00000000, 0x00002000, 0x00000000, 0x00000000, 0x00002000, 0x00002000, 0x00002000, 
279                         0x00000020, 0x00000000, 0x00002020, 0x00000000, 0x00000020, 0x00002000, 0x00002020, 0x00002000, 
280                         0x00000000, 0x00000020, 0x00002000, 0x00000020, 0x00000000, 0x00002020, 0x00002000, 0x00002020, 
281                         0x00000020, 0x00000020, 0x00002020, 0x00000020, 0x00000020, 0x00002020, 0x00002020, 0x00002020, 
282                         0x00000000, 0x00000000, 0x20000000, 0x00000000, 0x00000000, 0x20000000, 0x20000000, 0x20000000, 
283                         0x00200000, 0x00000000, 0x20200000, 0x00000000, 0x00200000, 0x20000000, 0x20200000, 0x20000000, 
284                         0x00000000, 0x00200000, 0x20000000, 0x00200000, 0x00000000, 0x20200000, 0x20000000, 0x20200000, 
285                         0x00200000, 0x00200000, 0x20200000, 0x00200000, 0x00200000, 0x20200000, 0x20200000, 0x20200000, 
286                         0x00000000, 0x00000000, 0x00004000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 
287                         0x00000040, 0x00000000, 0x00004040, 0x00000000, 0x00000040, 0x00004000, 0x00004040, 0x00004000, 
288                         0x00000000, 0x00000040, 0x00004000, 0x00000040, 0x00000000, 0x00004040, 0x00004000, 0x00004040, 
289                         0x00000040, 0x00000040, 0x00004040, 0x00000040, 0x00000040, 0x00004040, 0x00004040, 0x00004040, 
290                         0x00000000, 0x00000000, 0x40000000, 0x00000000, 0x00000000, 0x40000000, 0x40000000, 0x40000000, 
291                         0x00400000, 0x00000000, 0x40400000, 0x00000000, 0x00400000, 0x40000000, 0x40400000, 0x40000000, 
292                         0x00000000, 0x00400000, 0x40000000, 0x00400000, 0x00000000, 0x40400000, 0x40000000, 0x40400000, 
293                         0x00400000, 0x00400000, 0x40400000, 0x00400000, 0x00400000, 0x40400000, 0x40400000, 0x40400000, 
294                         0x00000000, 0x00000000, 0x00008000, 0x00000000, 0x00000000, 0x00008000, 0x00008000, 0x00008000, 
295                         0x00000080, 0x00000000, 0x00008080, 0x00000000, 0x00000080, 0x00008000, 0x00008080, 0x00008000, 
296                         0x00000000, 0x00000080, 0x00008000, 0x00000080, 0x00000000, 0x00008080, 0x00008000, 0x00008080, 
297                         0x00000080, 0x00000080, 0x00008080, 0x00000080, 0x00000080, 0x00008080, 0x00008080, 0x00008080, 
298                         0x00000000, 0x00000000, 0x80000000, 0x00000000, 0x00000000, 0x80000000, 0x80000000, 0x80000000, 
299                         0x00800000, 0x00000000, 0x80800000, 0x00000000, 0x00800000, 0x80000000, 0x80800000, 0x80000000, 
300                         0x00000000, 0x00800000, 0x80000000, 0x00800000, 0x00000000, 0x80800000, 0x80000000, 0x80800000, 
301                         0x00800000, 0x00800000, 0x80800000, 0x00800000, 0x00800000, 0x80800000, 0x80800000, 0x80800000 
302                 };
303
304                 internal static readonly uint[] fpTab = { 
305                         0x00000000, 0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00004000, 0x00000000, 0x00004040, 
306                         0x00000000, 0x00400000, 0x00000000, 0x00400040, 0x00000000, 0x00404000, 0x00000000, 0x00404040, 
307                         0x00000000, 0x40000000, 0x00000000, 0x40000040, 0x00000000, 0x40004000, 0x00000000, 0x40004040, 
308                         0x00000000, 0x40400000, 0x00000000, 0x40400040, 0x00000000, 0x40404000, 0x00000000, 0x40404040, 
309                         0x00000000, 0x00000000, 0x00000040, 0x00000000, 0x00004000, 0x00000000, 0x00004040, 0x00000000, 
310                         0x00400000, 0x00000000, 0x00400040, 0x00000000, 0x00404000, 0x00000000, 0x00404040, 0x00000000, 
311                         0x40000000, 0x00000000, 0x40000040, 0x00000000, 0x40004000, 0x00000000, 0x40004040, 0x00000000, 
312                         0x40400000, 0x00000000, 0x40400040, 0x00000000, 0x40404000, 0x00000000, 0x40404040, 0x00000000, 
313                         0x00000000, 0x00000000, 0x00000000, 0x00000010, 0x00000000, 0x00001000, 0x00000000, 0x00001010, 
314                         0x00000000, 0x00100000, 0x00000000, 0x00100010, 0x00000000, 0x00101000, 0x00000000, 0x00101010, 
315                         0x00000000, 0x10000000, 0x00000000, 0x10000010, 0x00000000, 0x10001000, 0x00000000, 0x10001010, 
316                         0x00000000, 0x10100000, 0x00000000, 0x10100010, 0x00000000, 0x10101000, 0x00000000, 0x10101010, 
317                         0x00000000, 0x00000000, 0x00000010, 0x00000000, 0x00001000, 0x00000000, 0x00001010, 0x00000000, 
318                         0x00100000, 0x00000000, 0x00100010, 0x00000000, 0x00101000, 0x00000000, 0x00101010, 0x00000000, 
319                         0x10000000, 0x00000000, 0x10000010, 0x00000000, 0x10001000, 0x00000000, 0x10001010, 0x00000000, 
320                         0x10100000, 0x00000000, 0x10100010, 0x00000000, 0x10101000, 0x00000000, 0x10101010, 0x00000000, 
321                         0x00000000, 0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x00000400, 0x00000000, 0x00000404, 
322                         0x00000000, 0x00040000, 0x00000000, 0x00040004, 0x00000000, 0x00040400, 0x00000000, 0x00040404, 
323                         0x00000000, 0x04000000, 0x00000000, 0x04000004, 0x00000000, 0x04000400, 0x00000000, 0x04000404, 
324                         0x00000000, 0x04040000, 0x00000000, 0x04040004, 0x00000000, 0x04040400, 0x00000000, 0x04040404, 
325                         0x00000000, 0x00000000, 0x00000004, 0x00000000, 0x00000400, 0x00000000, 0x00000404, 0x00000000, 
326                         0x00040000, 0x00000000, 0x00040004, 0x00000000, 0x00040400, 0x00000000, 0x00040404, 0x00000000, 
327                         0x04000000, 0x00000000, 0x04000004, 0x00000000, 0x04000400, 0x00000000, 0x04000404, 0x00000000, 
328                         0x04040000, 0x00000000, 0x04040004, 0x00000000, 0x04040400, 0x00000000, 0x04040404, 0x00000000, 
329                         0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000100, 0x00000000, 0x00000101, 
330                         0x00000000, 0x00010000, 0x00000000, 0x00010001, 0x00000000, 0x00010100, 0x00000000, 0x00010101, 
331                         0x00000000, 0x01000000, 0x00000000, 0x01000001, 0x00000000, 0x01000100, 0x00000000, 0x01000101, 
332                         0x00000000, 0x01010000, 0x00000000, 0x01010001, 0x00000000, 0x01010100, 0x00000000, 0x01010101, 
333                         0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000100, 0x00000000, 0x00000101, 0x00000000, 
334                         0x00010000, 0x00000000, 0x00010001, 0x00000000, 0x00010100, 0x00000000, 0x00010101, 0x00000000, 
335                         0x01000000, 0x00000000, 0x01000001, 0x00000000, 0x01000100, 0x00000000, 0x01000101, 0x00000000, 
336                         0x01010000, 0x00000000, 0x01010001, 0x00000000, 0x01010100, 0x00000000, 0x01010101, 0x00000000, 
337                         0x00000000, 0x00000000, 0x00000000, 0x00000080, 0x00000000, 0x00008000, 0x00000000, 0x00008080, 
338                         0x00000000, 0x00800000, 0x00000000, 0x00800080, 0x00000000, 0x00808000, 0x00000000, 0x00808080, 
339                         0x00000000, 0x80000000, 0x00000000, 0x80000080, 0x00000000, 0x80008000, 0x00000000, 0x80008080, 
340                         0x00000000, 0x80800000, 0x00000000, 0x80800080, 0x00000000, 0x80808000, 0x00000000, 0x80808080, 
341                         0x00000000, 0x00000000, 0x00000080, 0x00000000, 0x00008000, 0x00000000, 0x00008080, 0x00000000, 
342                         0x00800000, 0x00000000, 0x00800080, 0x00000000, 0x00808000, 0x00000000, 0x00808080, 0x00000000, 
343                         0x80000000, 0x00000000, 0x80000080, 0x00000000, 0x80008000, 0x00000000, 0x80008080, 0x00000000, 
344                         0x80800000, 0x00000000, 0x80800080, 0x00000000, 0x80808000, 0x00000000, 0x80808080, 0x00000000, 
345                         0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00002000, 0x00000000, 0x00002020, 
346                         0x00000000, 0x00200000, 0x00000000, 0x00200020, 0x00000000, 0x00202000, 0x00000000, 0x00202020, 
347                         0x00000000, 0x20000000, 0x00000000, 0x20000020, 0x00000000, 0x20002000, 0x00000000, 0x20002020, 
348                         0x00000000, 0x20200000, 0x00000000, 0x20200020, 0x00000000, 0x20202000, 0x00000000, 0x20202020, 
349                         0x00000000, 0x00000000, 0x00000020, 0x00000000, 0x00002000, 0x00000000, 0x00002020, 0x00000000, 
350                         0x00200000, 0x00000000, 0x00200020, 0x00000000, 0x00202000, 0x00000000, 0x00202020, 0x00000000, 
351                         0x20000000, 0x00000000, 0x20000020, 0x00000000, 0x20002000, 0x00000000, 0x20002020, 0x00000000, 
352                         0x20200000, 0x00000000, 0x20200020, 0x00000000, 0x20202000, 0x00000000, 0x20202020, 0x00000000, 
353                         0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x00000000, 0x00000800, 0x00000000, 0x00000808, 
354                         0x00000000, 0x00080000, 0x00000000, 0x00080008, 0x00000000, 0x00080800, 0x00000000, 0x00080808, 
355                         0x00000000, 0x08000000, 0x00000000, 0x08000008, 0x00000000, 0x08000800, 0x00000000, 0x08000808, 
356                         0x00000000, 0x08080000, 0x00000000, 0x08080008, 0x00000000, 0x08080800, 0x00000000, 0x08080808, 
357                         0x00000000, 0x00000000, 0x00000008, 0x00000000, 0x00000800, 0x00000000, 0x00000808, 0x00000000, 
358                         0x00080000, 0x00000000, 0x00080008, 0x00000000, 0x00080800, 0x00000000, 0x00080808, 0x00000000, 
359                         0x08000000, 0x00000000, 0x08000008, 0x00000000, 0x08000800, 0x00000000, 0x08000808, 0x00000000, 
360                         0x08080000, 0x00000000, 0x08080008, 0x00000000, 0x08080800, 0x00000000, 0x08080808, 0x00000000, 
361                         0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000200, 0x00000000, 0x00000202, 
362                         0x00000000, 0x00020000, 0x00000000, 0x00020002, 0x00000000, 0x00020200, 0x00000000, 0x00020202, 
363                         0x00000000, 0x02000000, 0x00000000, 0x02000002, 0x00000000, 0x02000200, 0x00000000, 0x02000202, 
364                         0x00000000, 0x02020000, 0x00000000, 0x02020002, 0x00000000, 0x02020200, 0x00000000, 0x02020202, 
365                         0x00000000, 0x00000000, 0x00000002, 0x00000000, 0x00000200, 0x00000000, 0x00000202, 0x00000000, 
366                         0x00020000, 0x00000000, 0x00020002, 0x00000000, 0x00020200, 0x00000000, 0x00020202, 0x00000000, 
367                         0x02000000, 0x00000000, 0x02000002, 0x00000000, 0x02000200, 0x00000000, 0x02000202, 0x00000000, 
368                         0x02020000, 0x00000000, 0x02020002, 0x00000000, 0x02020200, 0x00000000, 0x02020202, 0x00000000 
369                         };
370
371 /*              static DESTransform ()
372                 {
373                         spBoxes = new uint [64 * 8];
374         
375                         int [] pBox = new int [32];
376         
377                         for (int p = 0; p < 32; p++) {
378                                 for (int i = 0; i < 32; i++) {
379                                         if (p == pTab [i]) {
380                                                 pBox [p] = i;
381                                                 break;
382                                         }
383                                 }
384                         }
385         
386                         for (int s = 0; s < 8; s++) { // for each S-box
387                                 int sOff = s << 6;
388         
389                                 for (int i = 0; i < 64; i++) { // inputs
390                                         uint sp=0;
391         
392                                         int indx = (i & 0x20) | ((i & 1) << 4) | ((i >> 1) & 0xF);
393         
394                                         for (int j = 0; j < 4; j++) { // for each bit in the output
395                                                 if ((sBoxes [sOff + indx] & (8 >> j)) != 0) {
396                                                         sp |= (uint) (1 << (31 - pBox [(s << 2) + j]));
397                                                 }
398                                         }
399         
400                                         spBoxes [sOff + i] = sp;
401                                 }
402                         }
403
404                         leftRotTotal = new byte [leftRot.Length];
405         
406                         for (int i = 0; i < leftRot.Length; i++) {
407                                 int r = 0;
408                                 for (int j = 0; j <= i; r += leftRot [j++]) {
409                                         // no statement (confuse the compiler == warning)
410                                 }
411                                 leftRotTotal [i]  = (byte) r;
412                         }
413
414                         InitPermutationTable (ipBits, out ipTab);
415                         InitPermutationTable (fpBits, out fpTab);
416                 }
417 */      
418                 // Default constructor.
419                 internal DESTransform (SymmetricAlgorithm symmAlgo, bool encryption, byte[] key, byte[] iv) 
420                         : base (symmAlgo, encryption, iv)
421                 {
422                         byte[] clonedKey = null;
423 #if NET_2_0
424                         if (key == null) {
425                                 key = GetStrongKey ();
426                                 clonedKey = key; // no need to clone
427                         }
428 #endif
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 #if NET_2_0
663         [ComVisible (true)]
664 #endif
665         public sealed class DESCryptoServiceProvider : DES {
666         
667                 public DESCryptoServiceProvider ()
668                 {
669                 }
670         
671                 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV) 
672                 {
673                         return new DESTransform (this, false, rgbKey, rgbIV);
674                 }
675         
676                 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV) 
677                 {
678                         return new DESTransform (this, true, rgbKey, rgbIV);
679                 }
680         
681                 public override void GenerateIV () 
682                 {
683                         IVValue = KeyBuilder.IV (DESTransform.BLOCK_BYTE_SIZE);
684                 }
685         
686                 public override void GenerateKey () 
687                 {
688                         KeyValue = DESTransform.GetStrongKey ();
689                 }
690         }
691 }