一个Delphi写的DES算法, 翻译成C#
其实.NET Framework已经提供实现DES算法的类: System.Security.Cryptography.DESCryptoServiceProvider。之所以要把一个Delphi写的DES算法翻译成C#,是因为网友espnstar想用Delphi加密,C#解密,详见CSDN贴子: http://topic.csdn.net/t/20050726/18/4169690.html。
1// Des.cs - 一个Delphi写的DES算法, 翻译成C#
2// Wed 2005.09.14
3
4// public byte[] EncryBytes (byte[] inData, byte[] keyByte);
5// public byte[] DecryBytes (byte[] inData, byte[] keyByte);
6// public string EncryStr (string Str, string Key );
7// public string DecryStr (string Str, string Key );
8// public string EncryStrHex(string Str, string Key );
9// public string DecryStrHex(string StrHex, string Key );
10
11namespace Skyiv
12{
13 using System;
14 using System.Text;
15
16 enum TDesMode { dmEncry, dmDecry };
17
18 class Des
19 {
20 static readonly byte [] BitIP =
21 {
22 57, 49, 41, 33, 25, 17, 9, 1,
23 59, 51, 43, 35, 27, 19, 11, 3,
24 61, 53, 45, 37, 29, 21, 13, 5,
25 63, 55, 47, 39, 31, 23, 15, 7,
26 56, 48, 40, 32, 24, 16, 8, 0,
27 58, 50, 42, 34, 26, 18, 10, 2,
28 60, 52, 44, 36, 28, 20, 12, 4,
29 62, 54, 46, 38, 30, 22, 14, 6
30 };
31
32 static readonly byte [] BitCP =
33 {
34 39, 7, 47, 15, 55, 23, 63, 31,
35 38, 6, 46, 14, 54, 22, 62, 30,
36 37, 5, 45, 13, 53, 21, 61, 29,
37 36, 4, 44, 12, 52, 20, 60, 28,
38 35, 3, 43, 11, 51, 19, 59, 27,
39 34, 2, 42, 10, 50, 18, 58, 26,
40 33, 1, 41, 9, 49, 17, 57, 25,
41 32, 0, 40, 8, 48, 16, 56, 24
42 };
43
44 static readonly int [] BitExp =
45 {
46 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 9,10,
47 11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,
48 21,22,23,24,23,24,25,26,27,28,27,28,29,30,31, 0
49 };
50
51 static readonly byte [] BitPM =
52 {
53 15, 6,19,20,28,11,27,16, 0,14,22,25, 4,17,30, 9,
54 1, 7,23,13,31,26, 2, 8,18,12,29, 5,21,10, 3,24
55 };
56
57 static readonly byte [,] sBox =
58 {
59 {
60 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
61 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
62 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
63 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
64 },
65 {
66 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
67 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
68 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
69 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
70 },
71 {
72 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
73 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
74 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
75 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
76 },
77 {
78 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
79 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
80 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
81 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
82 },
83 {
84 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
85 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
86 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
87 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
88 },
89 {
90 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
91 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
92 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
93 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
94 },
95 {
96 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
97 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
98 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
99 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
100 },
101 {
102 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
103 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
104 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
105 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
106 }
107 };
108
109 static readonly byte [] BitPMC1 =
110 {
111 56, 48, 40, 32, 24, 16, 8,
112 0, 57, 49, 41, 33, 25, 17,
113 9, 1, 58, 50, 42, 34, 26,
114 18, 10, 2, 59, 51, 43, 35,
115 62, 54, 46, 38, 30, 22, 14,
116 6, 61, 53, 45, 37, 29, 21,
117 13, 5, 60, 52, 44, 36, 28,
118 20, 12, 4, 27, 19, 11, 3
119 };
120
121 static readonly byte [] BitPMC2 =
122 {
123 13, 16, 10, 23, 0, 4,
124 2, 27, 14, 5, 20, 9,
125 22, 18, 11, 3, 25, 7,
126 15, 6, 26, 19, 12, 1,
127 40, 51, 30, 36, 46, 54,
128 29, 39, 50, 44, 32, 47,
129 43, 48, 38, 55, 33, 52,
130 45, 41, 49, 35, 28, 31
131 };
132
133 byte [][] SubKey;
134
135 public Des()
136 {
137 SubKey = new byte [16][];
138 for (int i = 0; i < SubKey.Length; i++)
139 {
140 SubKey[i] = new byte [6];
141 }
142 }
143
144 void initPermutation(byte [] inData)
145 {
146 byte [] newData = new byte [8];
147 for (int i = 0; i < 64; i++)
148 {
149 if ((inData[BitIP[i] >> 3] & (1 << (7 - (BitIP[i] & 0x07)))) != 0)
150 {
151 newData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
152 }
153 }
154 Array.Copy(newData, inData, 8);
155 }
156
157 void conversePermutation(byte [] inData)
158 {
159 byte [] newData = new byte [8];
160 for (int i = 0; i < 64; i++)
161 {
162 if ((inData[BitCP[i] >> 3] & (1 << (7 - (BitCP[i] & 0x07)))) != 0)
163 {
164 newData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
165 }
166 }
167 Array.Copy(newData, inData, 8);
168 }
169
170 void expand(byte [] inData, byte [] outData)
171 {
172 Array.Clear(outData, 0, 6);
173 for (int i = 0; i < 48; i++)
174 {
175 if ((inData[BitExp[i] >> 3] & (1 << (7 - (BitExp[i] & 0x07)))) != 0)
176 {
177 outData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
178 }
179 }
180 }
181
182 void permutation(byte [] inData)
183 {
184 byte [] newData = new byte [4];
185 for (int i = 0; i < 32; i++)
186 {
187 if ((inData[BitPM[i] >> 3] & (1 << (7 - (BitPM[i] & 0x07)))) != 0)
188 {
189 newData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
190 }
191 }
192 Array.Copy(newData, inData, 4);
193 }
194
195 byte si(byte s, byte inByte)
196 {
197 int c = (inByte & 0x20) | ((inByte & 0x1e) >> 1) | ((inByte & 0x01) << 4);
198 return (byte)(sBox[s,c] & 0x0f);
199 }
200
201 void permutationChoose1(byte [] inData, byte [] outData)
202 {
203 Array.Clear(outData, 0, 7);
204 for (int i = 0; i < 56; i++)
205 {
206 if ((inData[BitPMC1[i] >> 3] & (1 << (7 - (BitPMC1[i] & 0x07)))) != 0)
207 {
208 outData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
209 }
210 }
211 }
212
213 void permutationChoose2(byte [] inData, byte [] outData)
214 {
215 Array.Clear(outData, 0, 6);
216 for (int i = 0; i < 48; i++)
217 {
218 if ((inData[BitPMC2[i] >> 3] & (1 << (7 - (BitPMC2[i] & 0x07)))) != 0)
219 {
220 outData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
221 }
222 }
223 }
224
225 void cycleMove(byte [] inData, byte bitMove)
226 {
227 for (int i = 0; i < bitMove; i++)
228 {
229 inData[0] = (byte)((inData[0] << 1) | (inData[1] >> 7));
230 inData[1] = (byte)((inData[1] << 1) | (inData[2] >> 7));
231 inData[2] = (byte)((inData[2] << 1) | (inData[3] >> 7));
232 inData[3] = (byte)((inData[3] << 1) | ((inData[0] & 0x10) >> 4));
233 inData[0] = (byte)(inData[0] & 0x0f);
234 }
235 }
236
237 static readonly byte [] bitDisplace = { 1,1,2,2, 2,2,2,2, 1,2,2,2, 2,2,2,1 };
238
239 void makeKey(byte [] inKey, byte [][] outKey)
240 {
241 byte [] outData56 = new byte [7];
242 byte [] key28l = new byte [4];
243 byte [] key28r = new byte [4];
244 byte [] key56o = new byte [7];
245
246 permutationChoose1(inKey, outData56);
247 key28l[0] = (byte)(outData56[0] >> 4);
248 key28l[1] = (byte)((outData56[0] << 4) | (outData56[1] >> 4));
249 key28l[2] = (byte)((outData56[1] << 4) | (outData56[2] >> 4));
250 key28l[3] = (byte)((outData56[2] << 4) | (outData56[3] >> 4));
251 key28r[0] = (byte)(outData56[3] & 0x0f);
252 key28r[1] = (byte)(outData56[4]);
253 key28r[2] = (byte)(outData56[5]);
254 key28r[3] = (byte)(outData56[6]);
255
256 for (int i = 0; i < 16; i++)
257 {
258 cycleMove(key28l, bitDisplace[i]);
259 cycleMove(key28r, bitDisplace[i]);
260 key56o[0] = (byte)((key28l[0] << 4) | (key28l[1] >> 4));
261 key56o[1] = (byte)((key28l[1] << 4) | (key28l[2] >> 4));
262 key56o[2] = (byte)((key28l[2] << 4) | (key28l[3] >> 4));
263 key56o[3] = (byte)((key28l[3] << 4) | (key28r[0]));
264 key56o[4] = (byte)(key28r[1]);
265 key56o[5] = (byte)(key28r[2]);
266 key56o[6] = (byte)(key28r[3]);
267 permutationChoose2(key56o, outKey[i]);
268 };
269 }
270
271 void encry(byte [] inData, byte [] subKey, byte [] outData)
272 {
273 byte [] outBuf = new byte [6];
274 byte [] buf = new byte [8];
275
276 expand(inData, outBuf);
277 for (int i = 0; i < 6; i++) outBuf[i] = (byte)(outBuf[i] ^ subKey[i]);
278 // outBuf xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
279 buf[0] = (byte)(outBuf[0] >> 2); //xxxxxx -> 2
280 buf[1] = (byte)(((outBuf[0] & 0x03) << 4) | (outBuf[1] >> 4)); // 4 <- xx xxxx -> 4
281 buf[2] = (byte)(((outBuf[1] & 0x0f) << 2) | (outBuf[2] >> 6)); // 2 <- xxxx xx -> 6
282 buf[3] = (byte)(outBuf[2] & 0x3f); // xxxxxx
283 buf[4] = (byte)(outBuf[3] >> 2); // xxxxxx
284 buf[5] = (byte)(((outBuf[3] & 0x03) << 4) | (outBuf[4] >> 4)); // xx xxxx
285 buf[6] = (byte)(((outBuf[4] & 0x0f) << 2) | (outBuf[5] >> 6)); // xxxx xx
286 buf[7] = (byte)(outBuf[5] & 0x3f); // xxxxxx
287 for (int i = 0; i < 8; i++) buf[i] = si((byte)i, buf[i]);
288 for (int i = 0; i < 4; i++) outBuf[i] = (byte)((buf[i*2] << 4) | buf[i*2+1]);
289 permutation(outBuf);
290 for (int i = 0; i < 4; i++) outData[i] = outBuf[i];
291 }
292
293 // inData, outData 都为 8 Bytes,否则出错
294 void desData(TDesMode desMode, byte [] inData, byte [] outData)
295 {
296 int i, j;
297 byte [] temp = new byte [4];
298 byte [] buf = new byte [4];
299
300 for (i = 0; i < 8; i++) outData[i] = inData[i];
301 initPermutation(outData);
302 if (desMode == TDesMode.dmEncry)
303 {
304 for (i = 0; i < 16; i++)
305 {
306 for (j = 0; j < 4; j++) temp[j] = outData[j]; //temp = Ln
307 for (j = 0; j < 4; j++) outData[j] = outData[j+4]; //Ln+1 = Rn
308 encry(outData, SubKey[i], buf); //Rn ==Kn==> buf
309 for (j = 0; j < 4; j++) outData[j+4] = (byte)(temp[j] ^ buf[j]); //Rn+1 = Ln^buf
310 };
311 for (j = 0; j < 4; j++) temp[j] = outData[j+4];
312 for (j = 0; j < 4; j++) outData[j+4] = outData[j];
313 for (j = 0; j < 4; j++) outData[j] = temp[j];
314 }
315 else if (desMode == TDesMode.dmDecry)
316 {
317 for (i = 15; i >= 0; i--)
318 {
319 for (j = 0; j < 4; j++) temp[j] = outData[j];
320 for (j = 0; j < 4; j++) outData[j] = outData[j+4];
321 encry(outData, SubKey[i], buf);
322 for (j = 0; j < 4; j++) outData[j+4] = (byte)(temp[j] ^ buf[j]);
323 };
324 for (j = 0; j < 4; j++) temp[j] = outData[j+4];
325 for (j = 0; j < 4; j++) outData[j+4] = outData[j];
326 for (j = 0; j < 4; j++) outData[j] = temp[j];
327 };
328 conversePermutation(outData);
329 }
330
331 byte [] Redim(byte [] arr, int newSize)
332 {
333 if (newSize == arr.Length) return arr;
334 byte [] newArr = new byte [newSize];
335 Array.Copy(arr, 0, newArr, 0, Math.Min(arr.Length, newSize));
336 return newArr;
337 }
338
339 //////////////////////////////////////////////////////////////
340
341 public byte [] EncryBytes(byte [] inData, byte [] keyByte)
342 {
343 byte [] tmpByte = new byte [8];
344 byte [] outByte = new byte [8];
345
346 if ((inData.Length > 0) && (inData[inData.Length-1] == 0))
347 {
348 throw new ArgumentException("The last byte is 0.", "inData");
349 }
350 if (inData.Length % 8 != 0) inData = Redim(inData, (inData.Length+7)/8*8);
351 if (keyByte.Length != 8) keyByte = Redim(keyByte, 8);
352 makeKey(keyByte, SubKey);
353
354 byte [] outData = new byte [inData.Length];
355 for (int i = 0; i < inData.Length / 8; i++)
356 {
357 for (int j = 0; j < 8; j++)
358 {
359 tmpByte[j] = inData[i * 8 + j];
360 }
361 desData(TDesMode.dmEncry, tmpByte, outByte);
362 for (int j = 0; j < 8; j++)
363 {
364 outData[i * 8 + j] = outByte[j];
365 }
366 };
367
368 return outData;
369 }
370
371 public byte [] DecryBytes(byte [] inData, byte [] keyByte)
372 {
373 byte [] tmpByte = new byte [8];
374 byte [] outByte = new byte [8];
375
376 if (keyByte.Length != 8) keyByte = Redim(keyByte, 8);
377 makeKey(keyByte, SubKey);
378
379 byte [] outData = new byte [(inData.Length+7)/8*8];
380 for (int i = 0; i < inData.Length / 8; i++)
381 {
382 for (int j = 0; j < 8; j++)
383 {
384 tmpByte[j] = inData[i * 8 + j];
385 }
386 desData(TDesMode.dmDecry, tmpByte, outByte);
387 for (int j = 0; j < 8; j++)
388 {
389 outData[i * 8 + j] = outByte[j];
390 }
391 };
392
393 int n = outData.Length - 1;
394 while (n >= 0 && outData[n] == 0) --n;
395 return Redim(outData, n+1);
396 }
397
398 public string EncryStr(string Str, string Key)
399 {
400 byte [] inData = Encoding.UTF8.GetBytes(Str);
401 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
402 byte [] tmpByte = EncryBytes(inData, keyByte);
403 StringBuilder tmpStr = new StringBuilder();
404 foreach (byte b in tmpByte)
405 {
406 tmpStr.Append((char)b);
407 }
408 return tmpStr.ToString();
409 }
410
411 public string DecryStr(string Str, string Key)
412 {
413 byte [] inData = new byte [Str.Length];
414 for (int i = 0; i < Str.Length; i++)
415 {
416 inData[i] = (byte)Str[i];
417 }
418 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
419 byte [] tmpByte = DecryBytes(inData, keyByte);
420 return Encoding.UTF8.GetString(tmpByte);
421 }
422
423 public string EncryStrHex(string Str, string Key)
424 {
425 byte [] inData = Encoding.UTF8.GetBytes(Str);
426 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
427 byte [] tmpByte = EncryBytes(inData, keyByte);
428 StringBuilder tmpStr = new StringBuilder();
429 foreach (byte b in tmpByte)
430 {
431 tmpStr.AppendFormat("{0:X2}", b);
432 }
433 return tmpStr.ToString();
434 }
435
436 public string DecryStrHex(string StrHex, string Key)
437 {
438 if (StrHex.Length % 2 != 0)
439 {
440 throw new ArgumentException("String length must be even.", "StrHex");
441 }
442 byte [] inData = new byte [StrHex.Length / 2];
443 for (int i = 0; i < StrHex.Length; i += 2)
444 {
445 inData[i/2] = (byte)(Uri.FromHex(StrHex[i])*16 + Uri.FromHex(StrHex[i+1]));
446 }
447 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
448 byte [] tmpByte = DecryBytes(inData, keyByte);
449 return Encoding.UTF8.GetString(tmpByte);
450 }
451 } // End of class Des
452} // End of namespace Skyiv
感谢网友espnstar提供Delphi版的源程序:
2// Wed 2005.09.14
3
4// public byte[] EncryBytes (byte[] inData, byte[] keyByte);
5// public byte[] DecryBytes (byte[] inData, byte[] keyByte);
6// public string EncryStr (string Str, string Key );
7// public string DecryStr (string Str, string Key );
8// public string EncryStrHex(string Str, string Key );
9// public string DecryStrHex(string StrHex, string Key );
10
11namespace Skyiv
12{
13 using System;
14 using System.Text;
15
16 enum TDesMode { dmEncry, dmDecry };
17
18 class Des
19 {
20 static readonly byte [] BitIP =
21 {
22 57, 49, 41, 33, 25, 17, 9, 1,
23 59, 51, 43, 35, 27, 19, 11, 3,
24 61, 53, 45, 37, 29, 21, 13, 5,
25 63, 55, 47, 39, 31, 23, 15, 7,
26 56, 48, 40, 32, 24, 16, 8, 0,
27 58, 50, 42, 34, 26, 18, 10, 2,
28 60, 52, 44, 36, 28, 20, 12, 4,
29 62, 54, 46, 38, 30, 22, 14, 6
30 };
31
32 static readonly byte [] BitCP =
33 {
34 39, 7, 47, 15, 55, 23, 63, 31,
35 38, 6, 46, 14, 54, 22, 62, 30,
36 37, 5, 45, 13, 53, 21, 61, 29,
37 36, 4, 44, 12, 52, 20, 60, 28,
38 35, 3, 43, 11, 51, 19, 59, 27,
39 34, 2, 42, 10, 50, 18, 58, 26,
40 33, 1, 41, 9, 49, 17, 57, 25,
41 32, 0, 40, 8, 48, 16, 56, 24
42 };
43
44 static readonly int [] BitExp =
45 {
46 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 9,10,
47 11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,
48 21,22,23,24,23,24,25,26,27,28,27,28,29,30,31, 0
49 };
50
51 static readonly byte [] BitPM =
52 {
53 15, 6,19,20,28,11,27,16, 0,14,22,25, 4,17,30, 9,
54 1, 7,23,13,31,26, 2, 8,18,12,29, 5,21,10, 3,24
55 };
56
57 static readonly byte [,] sBox =
58 {
59 {
60 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
61 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
62 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
63 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13
64 },
65 {
66 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
67 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
68 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
69 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9
70 },
71 {
72 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
73 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
74 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
75 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12
76 },
77 {
78 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
79 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
80 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
81 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14
82 },
83 {
84 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
85 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
86 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
87 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3
88 },
89 {
90 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
91 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
92 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
93 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13
94 },
95 {
96 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
97 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
98 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
99 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12
100 },
101 {
102 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
103 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
104 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
105 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11
106 }
107 };
108
109 static readonly byte [] BitPMC1 =
110 {
111 56, 48, 40, 32, 24, 16, 8,
112 0, 57, 49, 41, 33, 25, 17,
113 9, 1, 58, 50, 42, 34, 26,
114 18, 10, 2, 59, 51, 43, 35,
115 62, 54, 46, 38, 30, 22, 14,
116 6, 61, 53, 45, 37, 29, 21,
117 13, 5, 60, 52, 44, 36, 28,
118 20, 12, 4, 27, 19, 11, 3
119 };
120
121 static readonly byte [] BitPMC2 =
122 {
123 13, 16, 10, 23, 0, 4,
124 2, 27, 14, 5, 20, 9,
125 22, 18, 11, 3, 25, 7,
126 15, 6, 26, 19, 12, 1,
127 40, 51, 30, 36, 46, 54,
128 29, 39, 50, 44, 32, 47,
129 43, 48, 38, 55, 33, 52,
130 45, 41, 49, 35, 28, 31
131 };
132
133 byte [][] SubKey;
134
135 public Des()
136 {
137 SubKey = new byte [16][];
138 for (int i = 0; i < SubKey.Length; i++)
139 {
140 SubKey[i] = new byte [6];
141 }
142 }
143
144 void initPermutation(byte [] inData)
145 {
146 byte [] newData = new byte [8];
147 for (int i = 0; i < 64; i++)
148 {
149 if ((inData[BitIP[i] >> 3] & (1 << (7 - (BitIP[i] & 0x07)))) != 0)
150 {
151 newData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
152 }
153 }
154 Array.Copy(newData, inData, 8);
155 }
156
157 void conversePermutation(byte [] inData)
158 {
159 byte [] newData = new byte [8];
160 for (int i = 0; i < 64; i++)
161 {
162 if ((inData[BitCP[i] >> 3] & (1 << (7 - (BitCP[i] & 0x07)))) != 0)
163 {
164 newData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
165 }
166 }
167 Array.Copy(newData, inData, 8);
168 }
169
170 void expand(byte [] inData, byte [] outData)
171 {
172 Array.Clear(outData, 0, 6);
173 for (int i = 0; i < 48; i++)
174 {
175 if ((inData[BitExp[i] >> 3] & (1 << (7 - (BitExp[i] & 0x07)))) != 0)
176 {
177 outData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
178 }
179 }
180 }
181
182 void permutation(byte [] inData)
183 {
184 byte [] newData = new byte [4];
185 for (int i = 0; i < 32; i++)
186 {
187 if ((inData[BitPM[i] >> 3] & (1 << (7 - (BitPM[i] & 0x07)))) != 0)
188 {
189 newData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
190 }
191 }
192 Array.Copy(newData, inData, 4);
193 }
194
195 byte si(byte s, byte inByte)
196 {
197 int c = (inByte & 0x20) | ((inByte & 0x1e) >> 1) | ((inByte & 0x01) << 4);
198 return (byte)(sBox[s,c] & 0x0f);
199 }
200
201 void permutationChoose1(byte [] inData, byte [] outData)
202 {
203 Array.Clear(outData, 0, 7);
204 for (int i = 0; i < 56; i++)
205 {
206 if ((inData[BitPMC1[i] >> 3] & (1 << (7 - (BitPMC1[i] & 0x07)))) != 0)
207 {
208 outData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
209 }
210 }
211 }
212
213 void permutationChoose2(byte [] inData, byte [] outData)
214 {
215 Array.Clear(outData, 0, 6);
216 for (int i = 0; i < 48; i++)
217 {
218 if ((inData[BitPMC2[i] >> 3] & (1 << (7 - (BitPMC2[i] & 0x07)))) != 0)
219 {
220 outData[i >> 3] |= (byte)(1 << (7 - (i & 0x07)));
221 }
222 }
223 }
224
225 void cycleMove(byte [] inData, byte bitMove)
226 {
227 for (int i = 0; i < bitMove; i++)
228 {
229 inData[0] = (byte)((inData[0] << 1) | (inData[1] >> 7));
230 inData[1] = (byte)((inData[1] << 1) | (inData[2] >> 7));
231 inData[2] = (byte)((inData[2] << 1) | (inData[3] >> 7));
232 inData[3] = (byte)((inData[3] << 1) | ((inData[0] & 0x10) >> 4));
233 inData[0] = (byte)(inData[0] & 0x0f);
234 }
235 }
236
237 static readonly byte [] bitDisplace = { 1,1,2,2, 2,2,2,2, 1,2,2,2, 2,2,2,1 };
238
239 void makeKey(byte [] inKey, byte [][] outKey)
240 {
241 byte [] outData56 = new byte [7];
242 byte [] key28l = new byte [4];
243 byte [] key28r = new byte [4];
244 byte [] key56o = new byte [7];
245
246 permutationChoose1(inKey, outData56);
247 key28l[0] = (byte)(outData56[0] >> 4);
248 key28l[1] = (byte)((outData56[0] << 4) | (outData56[1] >> 4));
249 key28l[2] = (byte)((outData56[1] << 4) | (outData56[2] >> 4));
250 key28l[3] = (byte)((outData56[2] << 4) | (outData56[3] >> 4));
251 key28r[0] = (byte)(outData56[3] & 0x0f);
252 key28r[1] = (byte)(outData56[4]);
253 key28r[2] = (byte)(outData56[5]);
254 key28r[3] = (byte)(outData56[6]);
255
256 for (int i = 0; i < 16; i++)
257 {
258 cycleMove(key28l, bitDisplace[i]);
259 cycleMove(key28r, bitDisplace[i]);
260 key56o[0] = (byte)((key28l[0] << 4) | (key28l[1] >> 4));
261 key56o[1] = (byte)((key28l[1] << 4) | (key28l[2] >> 4));
262 key56o[2] = (byte)((key28l[2] << 4) | (key28l[3] >> 4));
263 key56o[3] = (byte)((key28l[3] << 4) | (key28r[0]));
264 key56o[4] = (byte)(key28r[1]);
265 key56o[5] = (byte)(key28r[2]);
266 key56o[6] = (byte)(key28r[3]);
267 permutationChoose2(key56o, outKey[i]);
268 };
269 }
270
271 void encry(byte [] inData, byte [] subKey, byte [] outData)
272 {
273 byte [] outBuf = new byte [6];
274 byte [] buf = new byte [8];
275
276 expand(inData, outBuf);
277 for (int i = 0; i < 6; i++) outBuf[i] = (byte)(outBuf[i] ^ subKey[i]);
278 // outBuf xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
279 buf[0] = (byte)(outBuf[0] >> 2); //xxxxxx -> 2
280 buf[1] = (byte)(((outBuf[0] & 0x03) << 4) | (outBuf[1] >> 4)); // 4 <- xx xxxx -> 4
281 buf[2] = (byte)(((outBuf[1] & 0x0f) << 2) | (outBuf[2] >> 6)); // 2 <- xxxx xx -> 6
282 buf[3] = (byte)(outBuf[2] & 0x3f); // xxxxxx
283 buf[4] = (byte)(outBuf[3] >> 2); // xxxxxx
284 buf[5] = (byte)(((outBuf[3] & 0x03) << 4) | (outBuf[4] >> 4)); // xx xxxx
285 buf[6] = (byte)(((outBuf[4] & 0x0f) << 2) | (outBuf[5] >> 6)); // xxxx xx
286 buf[7] = (byte)(outBuf[5] & 0x3f); // xxxxxx
287 for (int i = 0; i < 8; i++) buf[i] = si((byte)i, buf[i]);
288 for (int i = 0; i < 4; i++) outBuf[i] = (byte)((buf[i*2] << 4) | buf[i*2+1]);
289 permutation(outBuf);
290 for (int i = 0; i < 4; i++) outData[i] = outBuf[i];
291 }
292
293 // inData, outData 都为 8 Bytes,否则出错
294 void desData(TDesMode desMode, byte [] inData, byte [] outData)
295 {
296 int i, j;
297 byte [] temp = new byte [4];
298 byte [] buf = new byte [4];
299
300 for (i = 0; i < 8; i++) outData[i] = inData[i];
301 initPermutation(outData);
302 if (desMode == TDesMode.dmEncry)
303 {
304 for (i = 0; i < 16; i++)
305 {
306 for (j = 0; j < 4; j++) temp[j] = outData[j]; //temp = Ln
307 for (j = 0; j < 4; j++) outData[j] = outData[j+4]; //Ln+1 = Rn
308 encry(outData, SubKey[i], buf); //Rn ==Kn==> buf
309 for (j = 0; j < 4; j++) outData[j+4] = (byte)(temp[j] ^ buf[j]); //Rn+1 = Ln^buf
310 };
311 for (j = 0; j < 4; j++) temp[j] = outData[j+4];
312 for (j = 0; j < 4; j++) outData[j+4] = outData[j];
313 for (j = 0; j < 4; j++) outData[j] = temp[j];
314 }
315 else if (desMode == TDesMode.dmDecry)
316 {
317 for (i = 15; i >= 0; i--)
318 {
319 for (j = 0; j < 4; j++) temp[j] = outData[j];
320 for (j = 0; j < 4; j++) outData[j] = outData[j+4];
321 encry(outData, SubKey[i], buf);
322 for (j = 0; j < 4; j++) outData[j+4] = (byte)(temp[j] ^ buf[j]);
323 };
324 for (j = 0; j < 4; j++) temp[j] = outData[j+4];
325 for (j = 0; j < 4; j++) outData[j+4] = outData[j];
326 for (j = 0; j < 4; j++) outData[j] = temp[j];
327 };
328 conversePermutation(outData);
329 }
330
331 byte [] Redim(byte [] arr, int newSize)
332 {
333 if (newSize == arr.Length) return arr;
334 byte [] newArr = new byte [newSize];
335 Array.Copy(arr, 0, newArr, 0, Math.Min(arr.Length, newSize));
336 return newArr;
337 }
338
339 //////////////////////////////////////////////////////////////
340
341 public byte [] EncryBytes(byte [] inData, byte [] keyByte)
342 {
343 byte [] tmpByte = new byte [8];
344 byte [] outByte = new byte [8];
345
346 if ((inData.Length > 0) && (inData[inData.Length-1] == 0))
347 {
348 throw new ArgumentException("The last byte is 0.", "inData");
349 }
350 if (inData.Length % 8 != 0) inData = Redim(inData, (inData.Length+7)/8*8);
351 if (keyByte.Length != 8) keyByte = Redim(keyByte, 8);
352 makeKey(keyByte, SubKey);
353
354 byte [] outData = new byte [inData.Length];
355 for (int i = 0; i < inData.Length / 8; i++)
356 {
357 for (int j = 0; j < 8; j++)
358 {
359 tmpByte[j] = inData[i * 8 + j];
360 }
361 desData(TDesMode.dmEncry, tmpByte, outByte);
362 for (int j = 0; j < 8; j++)
363 {
364 outData[i * 8 + j] = outByte[j];
365 }
366 };
367
368 return outData;
369 }
370
371 public byte [] DecryBytes(byte [] inData, byte [] keyByte)
372 {
373 byte [] tmpByte = new byte [8];
374 byte [] outByte = new byte [8];
375
376 if (keyByte.Length != 8) keyByte = Redim(keyByte, 8);
377 makeKey(keyByte, SubKey);
378
379 byte [] outData = new byte [(inData.Length+7)/8*8];
380 for (int i = 0; i < inData.Length / 8; i++)
381 {
382 for (int j = 0; j < 8; j++)
383 {
384 tmpByte[j] = inData[i * 8 + j];
385 }
386 desData(TDesMode.dmDecry, tmpByte, outByte);
387 for (int j = 0; j < 8; j++)
388 {
389 outData[i * 8 + j] = outByte[j];
390 }
391 };
392
393 int n = outData.Length - 1;
394 while (n >= 0 && outData[n] == 0) --n;
395 return Redim(outData, n+1);
396 }
397
398 public string EncryStr(string Str, string Key)
399 {
400 byte [] inData = Encoding.UTF8.GetBytes(Str);
401 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
402 byte [] tmpByte = EncryBytes(inData, keyByte);
403 StringBuilder tmpStr = new StringBuilder();
404 foreach (byte b in tmpByte)
405 {
406 tmpStr.Append((char)b);
407 }
408 return tmpStr.ToString();
409 }
410
411 public string DecryStr(string Str, string Key)
412 {
413 byte [] inData = new byte [Str.Length];
414 for (int i = 0; i < Str.Length; i++)
415 {
416 inData[i] = (byte)Str[i];
417 }
418 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
419 byte [] tmpByte = DecryBytes(inData, keyByte);
420 return Encoding.UTF8.GetString(tmpByte);
421 }
422
423 public string EncryStrHex(string Str, string Key)
424 {
425 byte [] inData = Encoding.UTF8.GetBytes(Str);
426 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
427 byte [] tmpByte = EncryBytes(inData, keyByte);
428 StringBuilder tmpStr = new StringBuilder();
429 foreach (byte b in tmpByte)
430 {
431 tmpStr.AppendFormat("{0:X2}", b);
432 }
433 return tmpStr.ToString();
434 }
435
436 public string DecryStrHex(string StrHex, string Key)
437 {
438 if (StrHex.Length % 2 != 0)
439 {
440 throw new ArgumentException("String length must be even.", "StrHex");
441 }
442 byte [] inData = new byte [StrHex.Length / 2];
443 for (int i = 0; i < StrHex.Length; i += 2)
444 {
445 inData[i/2] = (byte)(Uri.FromHex(StrHex[i])*16 + Uri.FromHex(StrHex[i+1]));
446 }
447 byte [] keyByte = Encoding.UTF8.GetBytes(Key);
448 byte [] tmpByte = DecryBytes(inData, keyByte);
449 return Encoding.UTF8.GetString(tmpByte);
450 }
451 } // End of class Des
452} // End of namespace Skyiv
1unit Des;
2
3interface
4
5uses SysUtils;
6
7type
8 TKeyByte = array[0..5] of Byte;
9 TDesMode = (dmEncry, dmDecry);
10
11 function EncryStr(Str, Key: String): String;
12 function DecryStr(Str, Key: String): String;
13 function EncryStrHex(Str, Key: String): String;
14 function DecryStrHex(StrHex, Key: String): String;
15
16const
17 BitIP: array[0..63] of Byte =
18 (57, 49, 41, 33, 25, 17, 9, 1,
19 59, 51, 43, 35, 27, 19, 11, 3,
20 61, 53, 45, 37, 29, 21, 13, 5,
21 63, 55, 47, 39, 31, 23, 15, 7,
22 56, 48, 40, 32, 24, 16, 8, 0,
23 58, 50, 42, 34, 26, 18, 10, 2,
24 60, 52, 44, 36, 28, 20, 12, 4,
25 62, 54, 46, 38, 30, 22, 14, 6 );
26
27 BitCP: array[0..63] of Byte =
28 ( 39, 7, 47, 15, 55, 23, 63, 31,
29 38, 6, 46, 14, 54, 22, 62, 30,
30 37, 5, 45, 13, 53, 21, 61, 29,
31 36, 4, 44, 12, 52, 20, 60, 28,
32 35, 3, 43, 11, 51, 19, 59, 27,
33 34, 2, 42, 10, 50, 18, 58, 26,
34 33, 1, 41, 9, 49, 17, 57, 25,
35 32, 0, 40, 8, 48, 16, 56, 24 );
36
37 BitExp: array[0..47] of Integer =
38 ( 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 9,10,
39 11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,
40 21,22,23,24,23,24,25,26,27,28,27,28,29,30,31,0 );
41
42 BitPM: array[0..31] of Byte =
43 ( 15, 6,19,20,28,11,27,16, 0,14,22,25, 4,17,30, 9,
44 1, 7,23,13,31,26, 2, 8,18,12,29, 5,21,10, 3,24 );
45
46 sBox: array[0..7] of array[0..63] of Byte =
47 ( ( 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
48 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
49 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
50 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 ),
51
52 ( 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
53 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
54 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
55 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 ),
56
57 ( 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
58 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
59 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
60 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 ),
61
62 ( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
63 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
64 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
65 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 ),
66
67 ( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
68 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
69 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
70 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 ),
71
72 ( 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
73 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
74 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
75 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 ),
76
77 ( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
78 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
79 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
80 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 ),
81
82 ( 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
83 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
84 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
85 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 ) );
86
87 BitPMC1: array[0..55] of Byte =
88 ( 56, 48, 40, 32, 24, 16, 8,
89 0, 57, 49, 41, 33, 25, 17,
90 9, 1, 58, 50, 42, 34, 26,
91 18, 10, 2, 59, 51, 43, 35,
92 62, 54, 46, 38, 30, 22, 14,
93 6, 61, 53, 45, 37, 29, 21,
94 13, 5, 60, 52, 44, 36, 28,
95 20, 12, 4, 27, 19, 11, 3 );
96
97 BitPMC2: array[0..47] of Byte =
98 ( 13, 16, 10, 23, 0, 4,
99 2, 27, 14, 5, 20, 9,
100 22, 18, 11, 3, 25, 7,
101 15, 6, 26, 19, 12, 1,
102 40, 51, 30, 36, 46, 54,
103 29, 39, 50, 44, 32, 47,
104 43, 48, 38, 55, 33, 52,
105 45, 41, 49, 35, 28, 31 );
106
107var
108 subKey: array[0..15] of TKeyByte;
109
110implementation
111
112procedure initPermutation(var inData: array of Byte);
113var
114 newData: array[0..7] of Byte;
115 i: Integer;
116begin
117 FillChar(newData, 8, 0);
118 for i := 0 to 63 do
119 if (inData[BitIP[i] shr 3] and (1 shl (7- (BitIP[i] and $07)))) <> 0 then
120 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07)));
121 for i := 0 to 7 do inData[i] := newData[i];
122end;
123
124procedure conversePermutation(var inData: array of Byte);
125var
126 newData: array[0..7] of Byte;
127 i: Integer;
128begin
129 FillChar(newData, 8, 0);
130 for i := 0 to 63 do
131 if (inData[BitCP[i] shr 3] and (1 shl (7-(BitCP[i] and $07)))) <> 0 then
132 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07)));
133 for i := 0 to 7 do inData[i] := newData[i];
134end;
135
136procedure expand(inData: array of Byte; var outData: array of Byte);
137var
138 i: Integer;
139begin
140 FillChar(outData, 6, 0);
141 for i := 0 to 47 do
142 if (inData[BitExp[i] shr 3] and (1 shl (7-(BitExp[i] and $07)))) <> 0 then
143 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07)));
144end;
145
146procedure permutation(var inData: array of Byte);
147var
148 newData: array[0..3] of Byte;
149 i: Integer;
150begin
151 FillChar(newData, 4, 0);
152 for i := 0 to 31 do
153 if (inData[BitPM[i] shr 3] and (1 shl (7-(BitPM[i] and $07)))) <> 0 then
154 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07)));
155 for i := 0 to 3 do inData[i] := newData[i];
156end;
157
158function si(s,inByte: Byte): Byte;
159var
160 c: Byte;
161begin
162 c := (inByte and $20) or ((inByte and $1e) shr 1) or
163 ((inByte and $01) shl 4);
164 Result := (sBox[s][c] and $0f);
165end;
166
167procedure permutationChoose1(inData: array of Byte;
168 var outData: array of Byte);
169var
170 i: Integer;
171begin
172 FillChar(outData, 7, 0);
173 for i := 0 to 55 do
174 if (inData[BitPMC1[i] shr 3] and (1 shl (7-(BitPMC1[i] and $07)))) <> 0 then
175 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07)));
176end;
177
178
179
180
181procedure permutationChoose2(inData: array of Byte;
182 var outData: array of Byte);
183var
184 i: Integer;
185begin
186 FillChar(outData, 6, 0);
187 for i := 0 to 47 do
188 if (inData[BitPMC2[i] shr 3] and (1 shl (7-(BitPMC2[i] and $07)))) <> 0 then
189 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07)));
190end;
191
192procedure cycleMove(var inData: array of Byte; bitMove: Byte);
193var
194 i: Integer;
195begin
196 for i := 0 to bitMove - 1 do
197 begin
198 inData[0] := (inData[0] shl 1) or (inData[1] shr 7);
199 inData[1] := (inData[1] shl 1) or (inData[2] shr 7);
200 inData[2] := (inData[2] shl 1) or (inData[3] shr 7);
201 inData[3] := (inData[3] shl 1) or ((inData[0] and $10) shr 4);
202 inData[0] := (inData[0] and $0f);
203 end;
204end;
205
206procedure makeKey(inKey: array of Byte; var outKey: array of TKeyByte);
207const
208 bitDisplace: array[0..15] of Byte =
209 ( 1,1,2,2, 2,2,2,2, 1,2,2,2, 2,2,2,1 );
210var
211 outData56: array[0..6] of Byte;
212 key28l: array[0..3] of Byte;
213 key28r: array[0..3] of Byte;
214 key56o: array[0..6] of Byte;
215 i: Integer;
216begin
217 permutationChoose1(inKey, outData56);
218
219 key28l[0] := outData56[0] shr 4;
220 key28l[1] := (outData56[0] shl 4) or (outData56[1] shr 4);
221 key28l[2] := (outData56[1] shl 4) or (outData56[2] shr 4);
222 key28l[3] := (outData56[2] shl 4) or (outData56[3] shr 4);
223 key28r[0] := outData56[3] and $0f;
224 key28r[1] := outData56[4];
225 key28r[2] := outData56[5];
226 key28r[3] := outData56[6];
227
228 for i := 0 to 15 do
229 begin
230 cycleMove(key28l, bitDisplace[i]);
231 cycleMove(key28r, bitDisplace[i]);
232 key56o[0] := (key28l[0] shl 4) or (key28l[1] shr 4);
233 key56o[1] := (key28l[1] shl 4) or (key28l[2] shr 4);
234 key56o[2] := (key28l[2] shl 4) or (key28l[3] shr 4);
235 key56o[3] := (key28l[3] shl 4) or (key28r[0]);
236 key56o[4] := key28r[1];
237 key56o[5] := key28r[2];
238 key56o[6] := key28r[3];
239 permutationChoose2(key56o, outKey[i]);
240 end;
241end;
242
243procedure encry(inData, subKey: array of Byte;
244 var outData: array of Byte);
245var
246 outBuf: array[0..5] of Byte;
247 buf: array[0..7] of Byte;
248 i: Integer;
249begin
250 expand(inData, outBuf);
251 for i := 0 to 5 do outBuf[i] := outBuf[i] xor subKey[i];
252 // outBuf xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
253 buf[0] := outBuf[0] shr 2; //xxxxxx -> 2
254 buf[1] := ((outBuf[0] and $03) shl 4) or (outBuf[1] shr 4); // 4 <- xx xxxx -> 4
255 buf[2] := ((outBuf[1] and $0f) shl 2) or (outBuf[2] shr 6); // 2 <- xxxx xx -> 6
256 buf[3] := outBuf[2] and $3f; // xxxxxx
257 buf[4] := outBuf[3] shr 2; // xxxxxx
258 buf[5] := ((outBuf[3] and $03) shl 4) or (outBuf[4] shr 4); // xx xxxx
259 buf[6] := ((outBuf[4] and $0f) shl 2) or (outBuf[5] shr 6); // xxxx xx
260 buf[7] := outBuf[5] and $3f; // xxxxxx
261 for i := 0 to 7 do buf[i] := si(i, buf[i]);
262 for i := 0 to 3 do outBuf[i] := (buf[i*2] shl 4) or buf[i*2+1];
263 permutation(outBuf);
264 for i := 0 to 3 do outData[i] := outBuf[i];
265end;
266
267procedure desData(desMode: TDesMode;
268 inData: array of Byte; var outData: array of Byte);
269// inData, outData 都为8Bytes,否则出错
270var
271 i, j: Integer;
272 temp, buf: array[0..3] of Byte;
273begin
274 for i := 0 to 7 do outData[i] := inData[i];
275 initPermutation(outData);
276 if desMode = dmEncry then
277 begin
278 for i := 0 to 15 do
279 begin
280 for j := 0 to 3 do temp[j] := outData[j]; //temp = Ln
281 for j := 0 to 3 do outData[j] := outData[j + 4]; //Ln+1 = Rn
282 encry(outData, subKey[i], buf); //Rn ==Kn==> buf
283 for j := 0 to 3 do outData[j + 4] := temp[j] xor buf[j]; //Rn+1 = Ln^buf
284 end;
285
286 for j := 0 to 3 do temp[j] := outData[j + 4];
287 for j := 0 to 3 do outData[j + 4] := outData[j];
288 for j := 0 to 3 do outData[j] := temp[j];
289 end
290 else if desMode = dmDecry then
291 begin
292 for i := 15 downto 0 do
293 begin
294 for j := 0 to 3 do temp[j] := outData[j];
295 for j := 0 to 3 do outData[j] := outData[j + 4];
296 encry(outData, subKey[i], buf);
297 for j := 0 to 3 do outData[j + 4] := temp[j] xor buf[j];
298 end;
299 for j := 0 to 3 do temp[j] := outData[j + 4];
300 for j := 0 to 3 do outData[j + 4] := outData[j];
301 for j := 0 to 3 do outData[j] := temp[j];
302 end;
303 conversePermutation(outData);
304end;
305
306//////////////////////////////////////////////////////////////
307
308function EncryStr(Str, Key: String): String;
309var
310 StrByte, OutByte, KeyByte: array[0..7] of Byte;
311 StrResult: String;
312 I, J: Integer;
313begin
314 if (Length(Str) > 0) and (Ord(Str[Length(Str)]) = 0) then
315 raise Exception.Create('Error: the last char is NULL char.');
316 if Length(Key) < 8 then
317 while Length(Key) < 8 do Key := Key + Chr(0);
318 while Length(Str) mod 8 <> 0 do Str := Str + Chr(0);
319
320 for J := 0 to 7 do KeyByte[J] := Ord(Key[J + 1]);
321 makeKey(keyByte, subKey);
322
323 StrResult := '';
324
325 for I := 0 to Length(Str) div 8 - 1 do
326 begin
327 for J := 0 to 7 do
328 StrByte[J] := Ord(Str[I * 8 + J + 1]);
329 desData(dmEncry, StrByte, OutByte);
330 for J := 0 to 7 do
331 StrResult := StrResult + Chr(OutByte[J]);
332 end;
333
334 Result := StrResult;
335end;
336
337function DecryStr(Str, Key: String): String;
338var
339 StrByte, OutByte, KeyByte: array[0..7] of Byte;
340 StrResult: String;
341 I, J: Integer;
342begin
343 if Length(Key) < 8 then
344 while Length(Key) < 8 do Key := Key + Chr(0);
345
346 for J := 0 to 7 do KeyByte[J] := Ord(Key[J + 1]);
347 makeKey(keyByte, subKey);
348
349 StrResult := '';
350
351 for I := 0 to Length(Str) div 8 - 1 do
352 begin
353 for J := 0 to 7 do StrByte[J] := Ord(Str[I * 8 + J + 1]);
354 desData(dmDecry, StrByte, OutByte);
355 for J := 0 to 7 do
356 StrResult := StrResult + Chr(OutByte[J]);
357 end;
358 while (Length(StrResult) > 0) and
359 (Ord(StrResult[Length(StrResult)]) = 0) do
360 Delete(StrResult, Length(StrResult), 1);
361 Result := StrResult;
362end;
363
364///////////////////////////////////////////////////////////
365
366function EncryStrHex(Str, Key: String): String;
367var
368 StrResult, TempResult, Temp: String;
369 I: Integer;
370begin
371 TempResult := EncryStr(Str, Key);
372 StrResult := '';
373 for I := 0 to Length(TempResult) - 1 do
374 begin
375 Temp := Format('%x', [Ord(TempResult[I + 1])]);
376 if Length(Temp) = 1 then Temp := '0' + Temp;
377 StrResult := StrResult + Temp;
378 end;
379 Result := StrResult;
380end;
381
382function DecryStrHex(StrHex, Key: String): String;
383 function HexToInt(Hex: String): Integer;
384 var
385 I, Res: Integer;
386 ch: Char;
387 begin
388 Res := 0;
389 for I := 0 to Length(Hex) - 1 do
390 begin
391 ch := Hex[I + 1];
392 if (ch >= '0') and (ch <= '9') then
393 Res := Res * 16 + Ord(ch) - Ord('0')
394 else if (ch >= 'A') and (ch <= 'F') then
395 Res := Res * 16 + Ord(ch) - Ord('A') + 10
396 else if (ch >= 'a') and (ch <= 'f') then
397 Res := Res * 16 + Ord(ch) - Ord('a') + 10
398 else raise Exception.Create('Error: not a Hex String');
399 end;
400 Result := Res;
401 end;
402
403var
404 Str, Temp: String;
405 I: Integer;
406begin
407 Str := '';
408 for I := 0 to Length(StrHex) div 2 - 1 do
409 begin
410 Temp := Copy(StrHex, I * 2 + 1, 2);
411 Str := Str + Chr(HexToInt(Temp));
412 end;
413 Result := DecryStr(Str, Key);
414end;
415
416end.
2
3interface
4
5uses SysUtils;
6
7type
8 TKeyByte = array[0..5] of Byte;
9 TDesMode = (dmEncry, dmDecry);
10
11 function EncryStr(Str, Key: String): String;
12 function DecryStr(Str, Key: String): String;
13 function EncryStrHex(Str, Key: String): String;
14 function DecryStrHex(StrHex, Key: String): String;
15
16const
17 BitIP: array[0..63] of Byte =
18 (57, 49, 41, 33, 25, 17, 9, 1,
19 59, 51, 43, 35, 27, 19, 11, 3,
20 61, 53, 45, 37, 29, 21, 13, 5,
21 63, 55, 47, 39, 31, 23, 15, 7,
22 56, 48, 40, 32, 24, 16, 8, 0,
23 58, 50, 42, 34, 26, 18, 10, 2,
24 60, 52, 44, 36, 28, 20, 12, 4,
25 62, 54, 46, 38, 30, 22, 14, 6 );
26
27 BitCP: array[0..63] of Byte =
28 ( 39, 7, 47, 15, 55, 23, 63, 31,
29 38, 6, 46, 14, 54, 22, 62, 30,
30 37, 5, 45, 13, 53, 21, 61, 29,
31 36, 4, 44, 12, 52, 20, 60, 28,
32 35, 3, 43, 11, 51, 19, 59, 27,
33 34, 2, 42, 10, 50, 18, 58, 26,
34 33, 1, 41, 9, 49, 17, 57, 25,
35 32, 0, 40, 8, 48, 16, 56, 24 );
36
37 BitExp: array[0..47] of Integer =
38 ( 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 9,10,
39 11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20,
40 21,22,23,24,23,24,25,26,27,28,27,28,29,30,31,0 );
41
42 BitPM: array[0..31] of Byte =
43 ( 15, 6,19,20,28,11,27,16, 0,14,22,25, 4,17,30, 9,
44 1, 7,23,13,31,26, 2, 8,18,12,29, 5,21,10, 3,24 );
45
46 sBox: array[0..7] of array[0..63] of Byte =
47 ( ( 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
48 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
49 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
50 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 ),
51
52 ( 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
53 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
54 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
55 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 ),
56
57 ( 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
58 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
59 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
60 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 ),
61
62 ( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
63 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
64 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
65 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 ),
66
67 ( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
68 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
69 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
70 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 ),
71
72 ( 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
73 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
74 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
75 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 ),
76
77 ( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
78 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
79 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
80 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 ),
81
82 ( 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
83 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
84 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
85 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 ) );
86
87 BitPMC1: array[0..55] of Byte =
88 ( 56, 48, 40, 32, 24, 16, 8,
89 0, 57, 49, 41, 33, 25, 17,
90 9, 1, 58, 50, 42, 34, 26,
91 18, 10, 2, 59, 51, 43, 35,
92 62, 54, 46, 38, 30, 22, 14,
93 6, 61, 53, 45, 37, 29, 21,
94 13, 5, 60, 52, 44, 36, 28,
95 20, 12, 4, 27, 19, 11, 3 );
96
97 BitPMC2: array[0..47] of Byte =
98 ( 13, 16, 10, 23, 0, 4,
99 2, 27, 14, 5, 20, 9,
100 22, 18, 11, 3, 25, 7,
101 15, 6, 26, 19, 12, 1,
102 40, 51, 30, 36, 46, 54,
103 29, 39, 50, 44, 32, 47,
104 43, 48, 38, 55, 33, 52,
105 45, 41, 49, 35, 28, 31 );
106
107var
108 subKey: array[0..15] of TKeyByte;
109
110implementation
111
112procedure initPermutation(var inData: array of Byte);
113var
114 newData: array[0..7] of Byte;
115 i: Integer;
116begin
117 FillChar(newData, 8, 0);
118 for i := 0 to 63 do
119 if (inData[BitIP[i] shr 3] and (1 shl (7- (BitIP[i] and $07)))) <> 0 then
120 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07)));
121 for i := 0 to 7 do inData[i] := newData[i];
122end;
123
124procedure conversePermutation(var inData: array of Byte);
125var
126 newData: array[0..7] of Byte;
127 i: Integer;
128begin
129 FillChar(newData, 8, 0);
130 for i := 0 to 63 do
131 if (inData[BitCP[i] shr 3] and (1 shl (7-(BitCP[i] and $07)))) <> 0 then
132 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07)));
133 for i := 0 to 7 do inData[i] := newData[i];
134end;
135
136procedure expand(inData: array of Byte; var outData: array of Byte);
137var
138 i: Integer;
139begin
140 FillChar(outData, 6, 0);
141 for i := 0 to 47 do
142 if (inData[BitExp[i] shr 3] and (1 shl (7-(BitExp[i] and $07)))) <> 0 then
143 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07)));
144end;
145
146procedure permutation(var inData: array of Byte);
147var
148 newData: array[0..3] of Byte;
149 i: Integer;
150begin
151 FillChar(newData, 4, 0);
152 for i := 0 to 31 do
153 if (inData[BitPM[i] shr 3] and (1 shl (7-(BitPM[i] and $07)))) <> 0 then
154 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07)));
155 for i := 0 to 3 do inData[i] := newData[i];
156end;
157
158function si(s,inByte: Byte): Byte;
159var
160 c: Byte;
161begin
162 c := (inByte and $20) or ((inByte and $1e) shr 1) or
163 ((inByte and $01) shl 4);
164 Result := (sBox[s][c] and $0f);
165end;
166
167procedure permutationChoose1(inData: array of Byte;
168 var outData: array of Byte);
169var
170 i: Integer;
171begin
172 FillChar(outData, 7, 0);
173 for i := 0 to 55 do
174 if (inData[BitPMC1[i] shr 3] and (1 shl (7-(BitPMC1[i] and $07)))) <> 0 then
175 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07)));
176end;
177
178
179
180
181procedure permutationChoose2(inData: array of Byte;
182 var outData: array of Byte);
183var
184 i: Integer;
185begin
186 FillChar(outData, 6, 0);
187 for i := 0 to 47 do
188 if (inData[BitPMC2[i] shr 3] and (1 shl (7-(BitPMC2[i] and $07)))) <> 0 then
189 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07)));
190end;
191
192procedure cycleMove(var inData: array of Byte; bitMove: Byte);
193var
194 i: Integer;
195begin
196 for i := 0 to bitMove - 1 do
197 begin
198 inData[0] := (inData[0] shl 1) or (inData[1] shr 7);
199 inData[1] := (inData[1] shl 1) or (inData[2] shr 7);
200 inData[2] := (inData[2] shl 1) or (inData[3] shr 7);
201 inData[3] := (inData[3] shl 1) or ((inData[0] and $10) shr 4);
202 inData[0] := (inData[0] and $0f);
203 end;
204end;
205
206procedure makeKey(inKey: array of Byte; var outKey: array of TKeyByte);
207const
208 bitDisplace: array[0..15] of Byte =
209 ( 1,1,2,2, 2,2,2,2, 1,2,2,2, 2,2,2,1 );
210var
211 outData56: array[0..6] of Byte;
212 key28l: array[0..3] of Byte;
213 key28r: array[0..3] of Byte;
214 key56o: array[0..6] of Byte;
215 i: Integer;
216begin
217 permutationChoose1(inKey, outData56);
218
219 key28l[0] := outData56[0] shr 4;
220 key28l[1] := (outData56[0] shl 4) or (outData56[1] shr 4);
221 key28l[2] := (outData56[1] shl 4) or (outData56[2] shr 4);
222 key28l[3] := (outData56[2] shl 4) or (outData56[3] shr 4);
223 key28r[0] := outData56[3] and $0f;
224 key28r[1] := outData56[4];
225 key28r[2] := outData56[5];
226 key28r[3] := outData56[6];
227
228 for i := 0 to 15 do
229 begin
230 cycleMove(key28l, bitDisplace[i]);
231 cycleMove(key28r, bitDisplace[i]);
232 key56o[0] := (key28l[0] shl 4) or (key28l[1] shr 4);
233 key56o[1] := (key28l[1] shl 4) or (key28l[2] shr 4);
234 key56o[2] := (key28l[2] shl 4) or (key28l[3] shr 4);
235 key56o[3] := (key28l[3] shl 4) or (key28r[0]);
236 key56o[4] := key28r[1];
237 key56o[5] := key28r[2];
238 key56o[6] := key28r[3];
239 permutationChoose2(key56o, outKey[i]);
240 end;
241end;
242
243procedure encry(inData, subKey: array of Byte;
244 var outData: array of Byte);
245var
246 outBuf: array[0..5] of Byte;
247 buf: array[0..7] of Byte;
248 i: Integer;
249begin
250 expand(inData, outBuf);
251 for i := 0 to 5 do outBuf[i] := outBuf[i] xor subKey[i];
252 // outBuf xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx
253 buf[0] := outBuf[0] shr 2; //xxxxxx -> 2
254 buf[1] := ((outBuf[0] and $03) shl 4) or (outBuf[1] shr 4); // 4 <- xx xxxx -> 4
255 buf[2] := ((outBuf[1] and $0f) shl 2) or (outBuf[2] shr 6); // 2 <- xxxx xx -> 6
256 buf[3] := outBuf[2] and $3f; // xxxxxx
257 buf[4] := outBuf[3] shr 2; // xxxxxx
258 buf[5] := ((outBuf[3] and $03) shl 4) or (outBuf[4] shr 4); // xx xxxx
259 buf[6] := ((outBuf[4] and $0f) shl 2) or (outBuf[5] shr 6); // xxxx xx
260 buf[7] := outBuf[5] and $3f; // xxxxxx
261 for i := 0 to 7 do buf[i] := si(i, buf[i]);
262 for i := 0 to 3 do outBuf[i] := (buf[i*2] shl 4) or buf[i*2+1];
263 permutation(outBuf);
264 for i := 0 to 3 do outData[i] := outBuf[i];
265end;
266
267procedure desData(desMode: TDesMode;
268 inData: array of Byte; var outData: array of Byte);
269// inData, outData 都为8Bytes,否则出错
270var
271 i, j: Integer;
272 temp, buf: array[0..3] of Byte;
273begin
274 for i := 0 to 7 do outData[i] := inData[i];
275 initPermutation(outData);
276 if desMode = dmEncry then
277 begin
278 for i := 0 to 15 do
279 begin
280 for j := 0 to 3 do temp[j] := outData[j]; //temp = Ln
281 for j := 0 to 3 do outData[j] := outData[j + 4]; //Ln+1 = Rn
282 encry(outData, subKey[i], buf); //Rn ==Kn==> buf
283 for j := 0 to 3 do outData[j + 4] := temp[j] xor buf[j]; //Rn+1 = Ln^buf
284 end;
285
286 for j := 0 to 3 do temp[j] := outData[j + 4];
287 for j := 0 to 3 do outData[j + 4] := outData[j];
288 for j := 0 to 3 do outData[j] := temp[j];
289 end
290 else if desMode = dmDecry then
291 begin
292 for i := 15 downto 0 do
293 begin
294 for j := 0 to 3 do temp[j] := outData[j];
295 for j := 0 to 3 do outData[j] := outData[j + 4];
296 encry(outData, subKey[i], buf);
297 for j := 0 to 3 do outData[j + 4] := temp[j] xor buf[j];
298 end;
299 for j := 0 to 3 do temp[j] := outData[j + 4];
300 for j := 0 to 3 do outData[j + 4] := outData[j];
301 for j := 0 to 3 do outData[j] := temp[j];
302 end;
303 conversePermutation(outData);
304end;
305
306//////////////////////////////////////////////////////////////
307
308function EncryStr(Str, Key: String): String;
309var
310 StrByte, OutByte, KeyByte: array[0..7] of Byte;
311 StrResult: String;
312 I, J: Integer;
313begin
314 if (Length(Str) > 0) and (Ord(Str[Length(Str)]) = 0) then
315 raise Exception.Create('Error: the last char is NULL char.');
316 if Length(Key) < 8 then
317 while Length(Key) < 8 do Key := Key + Chr(0);
318 while Length(Str) mod 8 <> 0 do Str := Str + Chr(0);
319
320 for J := 0 to 7 do KeyByte[J] := Ord(Key[J + 1]);
321 makeKey(keyByte, subKey);
322
323 StrResult := '';
324
325 for I := 0 to Length(Str) div 8 - 1 do
326 begin
327 for J := 0 to 7 do
328 StrByte[J] := Ord(Str[I * 8 + J + 1]);
329 desData(dmEncry, StrByte, OutByte);
330 for J := 0 to 7 do
331 StrResult := StrResult + Chr(OutByte[J]);
332 end;
333
334 Result := StrResult;
335end;
336
337function DecryStr(Str, Key: String): String;
338var
339 StrByte, OutByte, KeyByte: array[0..7] of Byte;
340 StrResult: String;
341 I, J: Integer;
342begin
343 if Length(Key) < 8 then
344 while Length(Key) < 8 do Key := Key + Chr(0);
345
346 for J := 0 to 7 do KeyByte[J] := Ord(Key[J + 1]);
347 makeKey(keyByte, subKey);
348
349 StrResult := '';
350
351 for I := 0 to Length(Str) div 8 - 1 do
352 begin
353 for J := 0 to 7 do StrByte[J] := Ord(Str[I * 8 + J + 1]);
354 desData(dmDecry, StrByte, OutByte);
355 for J := 0 to 7 do
356 StrResult := StrResult + Chr(OutByte[J]);
357 end;
358 while (Length(StrResult) > 0) and
359 (Ord(StrResult[Length(StrResult)]) = 0) do
360 Delete(StrResult, Length(StrResult), 1);
361 Result := StrResult;
362end;
363
364///////////////////////////////////////////////////////////
365
366function EncryStrHex(Str, Key: String): String;
367var
368 StrResult, TempResult, Temp: String;
369 I: Integer;
370begin
371 TempResult := EncryStr(Str, Key);
372 StrResult := '';
373 for I := 0 to Length(TempResult) - 1 do
374 begin
375 Temp := Format('%x', [Ord(TempResult[I + 1])]);
376 if Length(Temp) = 1 then Temp := '0' + Temp;
377 StrResult := StrResult + Temp;
378 end;
379 Result := StrResult;
380end;
381
382function DecryStrHex(StrHex, Key: String): String;
383 function HexToInt(Hex: String): Integer;
384 var
385 I, Res: Integer;
386 ch: Char;
387 begin
388 Res := 0;
389 for I := 0 to Length(Hex) - 1 do
390 begin
391 ch := Hex[I + 1];
392 if (ch >= '0') and (ch <= '9') then
393 Res := Res * 16 + Ord(ch) - Ord('0')
394 else if (ch >= 'A') and (ch <= 'F') then
395 Res := Res * 16 + Ord(ch) - Ord('A') + 10
396 else if (ch >= 'a') and (ch <= 'f') then
397 Res := Res * 16 + Ord(ch) - Ord('a') + 10
398 else raise Exception.Create('Error: not a Hex String');
399 end;
400 Result := Res;
401 end;
402
403var
404 Str, Temp: String;
405 I: Integer;
406begin
407 Str := '';
408 for I := 0 to Length(StrHex) div 2 - 1 do
409 begin
410 Temp := Copy(StrHex, I * 2 + 1, 2);
411 Str := Str + Chr(HexToInt(Temp));
412 end;
413 Result := DecryStr(Str, Key);
414end;
415
416end.