DELPHI 的简单DES实现
一个小项目中要用到DES加解密,临时抱佛脚,在网上找了一番,还是好多的,从简单到复杂都有。
比较完整的实现有
PassByYou888大神的: https://github.com/PassByYou888/CoreCipher;但是没有包装,也比较大。
还有:https://github.com/winkelsdorf/DelphiEncryptionCompendium;这个中间的数据全部是用RawByteString来实现,还没仔细看
DCryptLib,这个没找到在哪下载,其它语言的Git上倒是有
各种博客上也有好多,比如:https://blog.csdn.net/yubiaohyb/article/details/50630035 ,这个能用,只是要求用ansistring,有时候不方便。
小项目,就不用大的了,用简单的就好。
就把 https://blog.csdn.net/yubiaohyb/article/details/50630035 这个包装下,直接用uncodestring
1 unit DESEncrypt; 2 3 interface 4 5 uses 6 System.SysUtils, System.Classes, System.Types, System.NetEncoding; 7 8 type 9 TKeyByte = array [0..5] of Byte; 10 TDesMode = (dmEncry, dmDecry); 11 12 TJkCryptograph = class 13 private 14 class var FCoverLen: Integer; 15 class var FSubKey: array [0..15] of TKeyByte; 16 class procedure InitPermutation(var inData: array of Byte); 17 class procedure Permutation(var inData: array of Byte); 18 class procedure PermutationChoose1(inData: array of Byte; var outData: array of Byte); 19 class procedure PermutationChoose2(inData: array of Byte; var outData: array of Byte); 20 class procedure ConversePermutation(var inData: array of Byte); 21 class procedure Expand(inData: array of Byte; var outData: array of Byte); 22 class function Sigma(si, inByte: Byte): Byte; 23 class procedure CycleMove(var inData: array of Byte; bitMove: Byte); 24 class procedure MakeKey(inKey: array of Byte; var outKey: array of TKeyByte); 25 class procedure CryptData(inData, subKey: array of Byte; var outData: array of Byte); 26 class procedure DesCryptData(desMode: TDesMode; inData: array of Byte; var outData: array of Byte); 27 28 public
//下面几个方法是包装的,方便现在的版本用 29 class function EncryptData(const AData, AKey: TBytes): TBytes; 30 class function DecryptData(const ACryptData, AKey: TBytes): TBytes; 31 32 class function EncryptStr(const AText, AKey: string): string; 33 class function DecryptStr(const AEncryptText, AKey: string): string; 34 class function EncryptStrHex(const AText, AKey: string): string; 35 class function DecryptStrHex(const AEncryptHexText, AKey: string): string; 36 class function EncryptStrBase64(const AText, AKey: string): string; 37 class function DecryptStrBase64(const AEncryptBase64Text, AKey: string): string; 38 end; 39 40 implementation 41 42 const 43 DefKEY = '12345678'; 44 45 BitIP: array[0..63] of Byte = 46 (57, 49, 41, 33, 25, 17, 9, 1, 47 59, 51, 43, 35, 27, 19, 11, 3, 48 61, 53, 45, 37, 29, 21, 13, 5, 49 63, 55, 47, 39, 31, 23, 15, 7, 50 56, 48, 40, 32, 24, 16, 8, 0, 51 58, 50, 42, 34, 26, 18, 10, 2, 52 60, 52, 44, 36, 28, 20, 12, 4, 53 62, 54, 46, 38, 30, 22, 14, 6 ); 54 55 BitCP: array[0..63] of Byte = 56 ( 39, 7, 47, 15, 55, 23, 63, 31, 57 38, 6, 46, 14, 54, 22, 62, 30, 58 37, 5, 45, 13, 53, 21, 61, 29, 59 36, 4, 44, 12, 52, 20, 60, 28, 60 35, 3, 43, 11, 51, 19, 59, 27, 61 34, 2, 42, 10, 50, 18, 58, 26, 62 33, 1, 41, 9, 49, 17, 57, 25, 63 32, 0, 40, 8, 48, 16, 56, 24 ); 64 65 BitExp: array[0..47] of Integer = 66 ( 31, 0, 1, 2, 3, 4, 3, 4, 5, 6, 7, 8, 7, 8, 9,10, 67 11,12,11,12,13,14,15,16,15,16,17,18,19,20,19,20, 68 21,22,23,24,23,24,25,26,27,28,27,28,29,30,31,0 ); 69 70 BitPM: array[0..31] of Byte = 71 ( 15, 6,19,20,28,11,27,16, 0,14,22,25, 4,17,30, 9, 72 1, 7,23,13,31,26, 2, 8,18,12,29, 5,21,10, 3,24 ); 73 74 sBox: array[0..7] of array[0..63] of Byte = 75 ( ( 14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7, 76 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8, 77 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0, 78 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13 ), 79 80 ( 15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10, 81 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5, 82 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15, 83 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9 ), 84 85 ( 10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8, 86 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1, 87 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7, 88 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12 ), 89 90 ( 7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15, 91 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9, 92 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4, 93 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14 ), 94 95 ( 2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9, 96 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6, 97 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14, 98 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3 ), 99 100 ( 12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11, 101 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8, 102 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6, 103 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13 ), 104 105 ( 4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1, 106 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6, 107 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2, 108 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12 ), 109 110 ( 13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7, 111 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2, 112 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8, 113 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11 ) ); 114 115 BitPMC1: array[0..55] of Byte = 116 ( 56, 48, 40, 32, 24, 16, 8, 117 0, 57, 49, 41, 33, 25, 17, 118 9, 1, 58, 50, 42, 34, 26, 119 18, 10, 2, 59, 51, 43, 35, 120 62, 54, 46, 38, 30, 22, 14, 121 6, 61, 53, 45, 37, 29, 21, 122 13, 5, 60, 52, 44, 36, 28, 123 20, 12, 4, 27, 19, 11, 3 ); 124 125 BitPMC2: array[0..47] of Byte = 126 ( 13, 16, 10, 23, 0, 4, 127 2, 27, 14, 5, 20, 9, 128 22, 18, 11, 3, 25, 7, 129 15, 6, 26, 19, 12, 1, 130 40, 51, 30, 36, 46, 54, 131 29, 39, 50, 44, 32, 47, 132 43, 48, 38, 55, 33, 52, 133 45, 41, 49, 35, 28, 31 ); 134 135 { TJkCryptograph } 136 137 class procedure TJkCryptograph.ConversePermutation(var inData: array of Byte); 138 var 139 newData: array[0..7] of Byte; 140 i: Integer; 141 begin 142 FillChar(newData, 8, 0); 143 for i := 0 to 63 do 144 if (inData[BitCP[i] shr 3] and (1 shl (7-(BitCP[i] and $07)))) <> 0 then 145 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07))); 146 for i := 0 to 7 do inData[i] := newData[i]; 147 148 end; 149 150 class procedure TJkCryptograph.CryptData(inData, subKey: array of Byte; var outData: array of Byte); 151 var 152 outBuf: array[0..5] of Byte; 153 buf: array[0..7] of Byte; 154 i: Integer; 155 begin 156 expand(inData, outBuf); 157 for i := 0 to 5 do outBuf[i] := outBuf[i] xor subKey[i]; 158 159 buf[0] := outBuf[0] shr 2; 160 buf[1] := ((outBuf[0] and $03) shl 4) or (outBuf[1] shr 4); 161 buf[2] := ((outBuf[1] and $0f) shl 2) or (outBuf[2] shr 6); 162 buf[3] := outBuf[2] and $3f; 163 buf[4] := outBuf[3] shr 2; 164 buf[5] := ((outBuf[3] and $03) shl 4) or (outBuf[4] shr 4); 165 buf[6] := ((outBuf[4] and $0f) shl 2) or (outBuf[5] shr 6); 166 buf[7] := outBuf[5] and $3f; 167 for i := 0 to 7 do buf[i] := sigma(i, buf[i]); 168 for i := 0 to 3 do outBuf[i] := (buf[i*2] shl 4) or buf[i*2+1]; 169 permutation(outBuf); 170 for i := 0 to 3 do outData[i] := outBuf[i]; 171 end; 172 173 class procedure TJkCryptograph.CycleMove(var inData: array of Byte; bitMove: Byte); 174 var 175 i: Integer; 176 begin 177 for i := 0 to bitMove - 1 do 178 begin 179 inData[0] := (inData[0] shl 1) or (inData[1] shr 7); 180 inData[1] := (inData[1] shl 1) or (inData[2] shr 7); 181 inData[2] := (inData[2] shl 1) or (inData[3] shr 7); 182 inData[3] := (inData[3] shl 1) or ((inData[0] and $10) shr 4); 183 inData[0] := (inData[0] and $0f); 184 end; 185 end; 186 187 class procedure TJkCryptograph.Expand(inData: array of Byte; var outData: array of Byte); 188 var 189 i: Integer; 190 begin 191 FillChar(outData, 6, 0); 192 for i := 0 to 47 do 193 if (inData[BitExp[i] shr 3] and (1 shl (7-(BitExp[i] and $07)))) <> 0 then 194 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07))); 195 end; 196 197 class procedure TJkCryptograph.InitPermutation(var inData: array of Byte); 198 var 199 newData: array[0..7] of Byte; 200 i: Integer; 201 begin 202 FillChar(newData, 8, 0); 203 for i := 0 to 63 do 204 if (inData[BitIP[i] shr 3] and (1 shl (7- (BitIP[i] and $07)))) <> 0 then 205 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07))); 206 for i := 0 to 7 do inData[i] := newData[i]; 207 end; 208 209 class procedure TJkCryptograph.MakeKey(inKey: array of Byte; var outKey: array of TKeyByte); 210 const 211 bitDisplace: array[0..15] of Byte = 212 ( 1,1,2,2, 2,2,2,2, 1,2,2,2, 2,2,2,1 ); 213 var 214 outData56: array[0..6] of Byte; 215 key28l: array[0..3] of Byte; 216 key28r: array[0..3] of Byte; 217 key56o: array[0..6] of Byte; 218 i: Integer; 219 begin 220 permutationChoose1(inKey, outData56); 221 222 key28l[0] := outData56[0] shr 4; 223 key28l[1] := (outData56[0] shl 4) or (outData56[1] shr 4); 224 key28l[2] := (outData56[1] shl 4) or (outData56[2] shr 4); 225 key28l[3] := (outData56[2] shl 4) or (outData56[3] shr 4); 226 key28r[0] := outData56[3] and $0f; 227 key28r[1] := outData56[4]; 228 key28r[2] := outData56[5]; 229 key28r[3] := outData56[6]; 230 231 for i := 0 to 15 do 232 begin 233 cycleMove(key28l, bitDisplace[i]); 234 cycleMove(key28r, bitDisplace[i]); 235 key56o[0] := (key28l[0] shl 4) or (key28l[1] shr 4); 236 key56o[1] := (key28l[1] shl 4) or (key28l[2] shr 4); 237 key56o[2] := (key28l[2] shl 4) or (key28l[3] shr 4); 238 key56o[3] := (key28l[3] shl 4) or (key28r[0]); 239 key56o[4] := key28r[1]; 240 key56o[5] := key28r[2]; 241 key56o[6] := key28r[3]; 242 permutationChoose2(key56o, outKey[i]); 243 end; 244 245 end; 246 247 class procedure TJkCryptograph.Permutation(var inData: array of Byte); 248 var 249 newData: array[0..3] of Byte; 250 i: Integer; 251 begin 252 FillChar(newData, 4, 0); 253 for i := 0 to 31 do 254 if (inData[BitPM[i] shr 3] and (1 shl (7-(BitPM[i] and $07)))) <> 0 then 255 newData[i shr 3] := newData[i shr 3] or (1 shl (7-(i and $07))); 256 for i := 0 to 3 do inData[i] := newData[i]; 257 258 end; 259 260 class procedure TJkCryptograph.PermutationChoose1(inData: array of Byte; var outData: array of Byte); 261 var 262 i: Integer; 263 begin 264 FillChar(outData, 7, 0); 265 for i := 0 to 55 do 266 if (inData[BitPMC1[i] shr 3] and (1 shl (7-(BitPMC1[i] and $07)))) <> 0 then 267 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07))); 268 269 end; 270 271 class procedure TJkCryptograph.PermutationChoose2(inData: array of Byte; var outData: array of Byte); 272 var 273 i: Integer; 274 begin 275 FillChar(outData, 6, 0); 276 for i := 0 to 47 do 277 if (inData[BitPMC2[i] shr 3] and (1 shl (7-(BitPMC2[i] and $07)))) <> 0 then 278 outData[i shr 3] := outData[i shr 3] or (1 shl (7-(i and $07))); 279 280 end; 281 282 class function TJkCryptograph.Sigma(si, inByte: Byte): Byte; 283 var 284 c: Byte; 285 begin 286 c := (inByte and $20) or ((inByte and $1e) shr 1) or 287 ((inByte and $01) shl 4); 288 Result := (sBox[si][c] and $0f); 289 290 end; 291 292 class procedure TJkCryptograph.DesCryptData(desMode: TDesMode; inData: array of Byte; var outData: array of Byte); 293 // inData, outData 都为8Bytes,否则出错 294 var 295 i, j: Integer; 296 temp, buf: array[0..3] of Byte; 297 begin 298 for i := 0 to 7 do outData[i] := inData[i]; 299 initPermutation(outData); 300 if desMode = dmEncry then 301 begin 302 for i := 0 to 15 do 303 begin 304 for j := 0 to 3 do temp[j] := outData[j]; 305 for j := 0 to 3 do outData[j] := outData[j + 4]; 306 CryptData(outData, FSubKey[i], buf); 307 for j := 0 to 3 do outData[j + 4] := temp[j] xor buf[j]; 308 end; 309 310 for j := 0 to 3 do temp[j] := outData[j + 4]; 311 for j := 0 to 3 do outData[j + 4] := outData[j]; 312 for j := 0 to 3 do outData[j] := temp[j]; 313 end 314 else if desMode = dmDecry then 315 begin 316 for i := 15 downto 0 do 317 begin 318 for j := 0 to 3 do temp[j] := outData[j]; 319 for j := 0 to 3 do outData[j] := outData[j + 4]; 320 CryptData(outData, FSubKey[i], buf); 321 for j := 0 to 3 do outData[j + 4] := temp[j] xor buf[j]; 322 end; 323 for j := 0 to 3 do temp[j] := outData[j + 4]; 324 for j := 0 to 3 do outData[j + 4] := outData[j]; 325 for j := 0 to 3 do outData[j] := temp[j]; 326 end; 327 conversePermutation(outData); 328 329 end; 330 331 class function TJkCryptograph.EncryptData(const AData, AKey: TBytes): TBytes; 332 var 333 tmpText, tmpKey, subText, resBytes: TBytes; 334 i, kenLen, textLen: Integer; 335 begin 336 kenLen := Length(AKey); 337 if kenLen < 8 then 338 begin 339 SetLength(tmpKey, 8); 340 for i := 0 to kenLen - 1 do 341 tmpKey[i] := AKey[i]; 342 for i := kenLen to 7 do 343 tmpKey[i] := 0; 344 end 345 else 346 begin 347 SetLength(tmpKey, 8); 348 Move(AKey[0], tmpKey[0], SizeOf(AKey[0]) * 8); 349 end; 350 351 textLen := Length(AData); 352 FCoverLen := 8 - textLen mod 8; 353 SetLength(tmpText, textLen + FCoverLen); 354 Move(AData[0], tmpText[0], textLen); 355 for i := 0 to FCoverLen - 1 do 356 tmpText[textLen + i] := FCoverLen; 357 358 MakeKey(tmpKey, FSubKey); 359 360 SetLength(subText, 8); 361 SetLength(resBytes, 8); 362 SetLength(Result, Length(tmpText)); 363 for i := 0 to Length(tmpText) div 8 - 1 do 364 begin 365 Move(tmpText[i*8], subText[0], SizeOf(tmpText[0]) * 8); 366 DesCryptData(dmEncry, subText, resBytes); 367 Move(resBytes[0], Result[i*8], 8); 368 end; 369 end; 370 371 class function TJkCryptograph.DecryptData(const ACryptData, AKey: TBytes): TBytes; 372 var 373 tmpKey, subText, resBytes, resBytesAll: TBytes; 374 i, kenLen: Integer; 375 begin 376 kenLen := Length(AKey); 377 if kenLen < 8 then 378 begin 379 SetLength(tmpKey, 8); 380 for i := 0 to kenLen - 1 do 381 tmpKey[i] := AKey[i]; 382 for i := kenLen to 7 do 383 tmpKey[i] := 0; 384 end 385 else 386 begin 387 SetLength(tmpKey, 8); 388 Move(AKey[0], tmpKey[0], SizeOf(AKey[0]) * 8); 389 end; 390 391 MakeKey(tmpKey, FSubKey); 392 393 SetLength(subText, 8); 394 SetLength(resBytes, 8); 395 SetLength(resBytesAll, Length(ACryptData)); 396 for i := 0 to Length(ACryptData) div 8 - 1 do 397 begin 398 Move(ACryptData[i*8], subText[0], SizeOf(ACryptData[0]) * 8); 399 DesCryptData(dmDecry, subText, resBytes); 400 Move(resBytes[0], resBytesAll[i*8], 8); 401 end; 402 403 SetLength(Result, Length(resBytesAll) - FCoverLen); 404 Move(resBytesAll[0], Result[0], Length(Result)); 405 end; 406 407 408 //这里可以用Unicode,ANSI,UTF8等,只要相应编码解密。但是加密结果不能用UTF8,因为编码页(CodePage)不一定支持中间的数据 409 class function TJkCryptograph.EncryptStr(const AText, AKey: string): string; 410 var 411 textBytes, keyBytes, encryBytes: TBytes; 412 begin 413 textBytes := TEncoding.Unicode.GetBytes(AText); 414 keyBytes := TEncoding.Unicode.GetBytes(AKey); 415 encryBytes := EncryptData(textBytes, keyBytes); 416 Result := TEncoding.Unicode.GetString(encryBytes); 417 end; 418 419 class function TJkCryptograph.EncryptStrBase64(const AText, AKey: string): string; 420 var 421 textBytes, keyBytes, encryBytes: TBytes; 422 begin 423 textBytes := TEncoding.UTF8.GetBytes(AText); 424 keyBytes := TEncoding.UTF8.GetBytes(AKey); 425 encryBytes := EncryptData(textBytes, keyBytes); 426 Result := TNetEncoding.Base64.EncodeBytesToString(encryBytes); 427 end; 428 429 class function TJkCryptograph.EncryptStrHex(const AText, AKey: string): string; 430 var 431 textBytes, keyBytes, encryBytes: TBytes; 432 i: Integer; 433 begin 434 textBytes := TEncoding.UTF8.GetBytes(AText); 435 keyBytes := TEncoding.UTF8.GetBytes(AKey); 436 encryBytes := EncryptData(textBytes, keyBytes); 437 Result := ''; 438 for i := 0 to Length(encryBytes) - 1 do 439 Result := Result + IntToHex(encryBytes[i], 2); 440 end; 441 442 class function TJkCryptograph.DecryptStr(const AEncryptText, AKey: string): string; 443 var 444 keyBytes, encryBytes, resBytes: TBytes; 445 begin 446 encryBytes := TEncoding.Unicode.GetBytes(AEncryptText); 447 keyBytes := TEncoding.Unicode.GetBytes(AKey); 448 resBytes := DecryptData(encryBytes, keyBytes); 449 Result := TEncoding.Unicode.GetString(resBytes); 450 end; 451 452 class function TJkCryptograph.DecryptStrBase64(const AEncryptBase64Text, AKey: string): string; 453 var 454 keyBytes, encryBytes, resBytes: TBytes; 455 begin 456 encryBytes := TNetEncoding.Base64.DecodeStringToBytes(AEncryptBase64Text); 457 keyBytes := TEncoding.UTF8.GetBytes(AKey); 458 resBytes := DecryptData(encryBytes, keyBytes); 459 Result := TEncoding.UTF8.GetString(resBytes); 460 end; 461 462 class function TJkCryptograph.DecryptStrHex(const AEncryptHexText, AKey: string): string; 463 var 464 keyBytes, encryBytes, resBytes: TBytes; 465 i: Integer; 466 begin 467 SetLength(encryBytes, Length(AEncryptHexText) div 2); 468 for i := 0 to Length(encryBytes) - 1 do 469 encryBytes[i] := StrToInt('$'+AEncryptHexText[i*2+1]+AEncryptHexText[i*2+2]); 470 keyBytes := TEncoding.UTF8.GetBytes(AKey); 471 resBytes := DecryptData(encryBytes, keyBytes); 472 Result := TEncoding.UTF8.GetString(resBytes); 473 end; 474 475 end.