2 // System.Security.Cryptography.DESCryptoServiceProvider
5 // Sergey Chaban (serge@wildwestsoftware.com)
6 // Sebastien Pouliot (sebastien@ximian.com)
8 // Portions (C) 2002 Motus Technologies Inc. (http://www.motus.com)
9 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
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:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
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.
33 using System.Runtime.InteropServices;
34 using Mono.Security.Cryptography;
36 namespace System.Security.Cryptography {
39 // a. FIPS PUB 46-3: Data Encryption Standard
40 // http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf
42 internal class DESTransform : SymmetricTransform {
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;
49 private byte[] keySchedule;
50 private byte[] byteBuff;
51 private uint[] dwordBuff;
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,
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,
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,
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,
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,
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,
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,
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
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
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
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,
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
191 private static readonly byte [] leftRot = {
192 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
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 };
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
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
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
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
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
373 /* static DESTransform ()
375 spBoxes = new uint [64 * 8];
377 int [] pBox = new int [32];
379 for (int p = 0; p < 32; p++) {
380 for (int i = 0; i < 32; i++) {
388 for (int s = 0; s < 8; s++) { // for each S-box
391 for (int i = 0; i < 64; i++) { // inputs
394 int indx = (i & 0x20) | ((i & 1) << 4) | ((i >> 1) & 0xF);
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]));
402 spBoxes [sOff + i] = sp;
406 leftRotTotal = new byte [leftRot.Length];
408 for (int i = 0; i < leftRot.Length; i++) {
410 for (int j = 0; j <= i; r += leftRot [j++]) {
411 // no statement (confuse the compiler == warning)
413 leftRotTotal [i] = (byte) r;
416 InitPermutationTable (ipBits, out ipTab);
417 InitPermutationTable (fpBits, out fpTab);
420 // Default constructor.
421 internal DESTransform (SymmetricAlgorithm symmAlgo, bool encryption, byte[] key, byte[] iv)
422 : base (symmAlgo, encryption, iv)
424 byte[] clonedKey = null;
426 key = GetStrongKey ();
427 clonedKey = key; // no need to clone
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);
435 if (clonedKey == null)
436 clonedKey = (byte[]) key.Clone ();
438 keySchedule = new byte [KEY_BYTE_SIZE * 16];
439 byteBuff = new byte [BLOCK_BYTE_SIZE];
440 dwordBuff = new uint [BLOCK_BYTE_SIZE / 4];
444 /* Permutation Tables are now precomputed.
445 private static void InitPermutationTable (byte[] pBits, out int[] permTab)
447 permTab = new int [8*2 * 8*2 * (64/32)];
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));
464 private uint CipherFunct (uint r, int n)
467 byte[] subkey = keySchedule;
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)];
483 internal static void Permutation (byte[] input, byte[] output, uint[] permTab, bool preSwap)
485 if (preSwap && BitConverter.IsLittleEndian)
488 int offs1 = (((int)(input [0]) >> 4)) << 1;
489 int offs2 = (1 << 5) + ((((int)input [0]) & 0xF) << 1);
491 uint d1 = permTab [offs1++] | permTab [offs2++];
492 uint d2 = permTab [offs1] | permTab [offs2];
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);
500 d1 |= permTab [offs1++] | permTab [offs2++];
501 d2 |= permTab [offs1] | permTab [offs2];
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);
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);
526 private static void BSwap (byte [] byteBuff)
528 byte t = byteBuff [0];
529 byteBuff [0] = byteBuff [3];
533 byteBuff [1] = byteBuff [2];
537 byteBuff [4] = byteBuff [7];
541 byteBuff [5] = byteBuff [6];
545 internal void SetKey (byte[] key)
547 // NOTE: see Fig. 3, Key schedule calculation, at page 20.
548 Array.Clear (keySchedule, 0, keySchedule.Length);
550 int keyBitSize = PC1.Length;
552 byte[] keyPC1 = new byte [keyBitSize]; // PC1-permuted key
553 byte[] keyRot = new byte [keyBitSize]; // PC1 & rotated
557 foreach (byte bitPos in PC1) {
558 keyPC1 [indx++] = (byte)((key [(int)bitPos >> 3] >> (7 ^ (bitPos & 7))) & 1);
562 for (int i = 0; i < KEY_BYTE_SIZE*2; i++) {
563 int b = keyBitSize >> 1;
565 for (j = 0; j < b; j++) {
566 int s = j + (int) leftRotTotal [i];
567 keyRot [j] = keyPC1 [s < b ? s : s - b];
570 for (j = b; j < keyBitSize; j++) {
571 int s = j + (int) leftRotTotal [i];
572 keyRot [j] = keyPC1 [s < keyBitSize ? s : s - b];
575 int keyOffs = i * KEY_BYTE_SIZE;
578 foreach (byte bitPos in PC2) {
579 if (keyRot [(int)bitPos] != 0) {
580 keySchedule [keyOffs + (j/6)] |= (byte) (0x80 >> ((j % 6) + 2));
587 // public helper for TripleDES
588 public void ProcessBlock (byte[] input, byte[] output)
590 Buffer.BlockCopy (input, 0, dwordBuff, 0, BLOCK_BYTE_SIZE);
593 uint d0 = dwordBuff [0];
594 uint d1 = dwordBuff [1];
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);
618 uint d1 = dwordBuff [0];
619 uint d0 = dwordBuff [1];
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);
643 Buffer.BlockCopy (dwordBuff, 0, output, 0, BLOCK_BYTE_SIZE);
646 protected override void ECB (byte[] input, byte[] output)
648 Permutation (input, output, ipTab, false);
649 ProcessBlock (output, byteBuff);
650 Permutation (byteBuff, output, fpTab, true);
653 static internal byte[] GetStrongKey ()
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);
663 public sealed class DESCryptoServiceProvider : DES {
665 public DESCryptoServiceProvider ()
669 public override ICryptoTransform CreateDecryptor (byte[] rgbKey, byte[] rgbIV)
671 return new DESTransform (this, false, rgbKey, rgbIV);
674 public override ICryptoTransform CreateEncryptor (byte[] rgbKey, byte[] rgbIV)
676 return new DESTransform (this, true, rgbKey, rgbIV);
679 public override void GenerateIV ()
681 IVValue = KeyBuilder.IV (DESTransform.BLOCK_BYTE_SIZE);
684 public override void GenerateKey ()
686 KeyValue = DESTransform.GetStrongKey ();